172 похожих чатов

@Tzirechnoy, Скажите, а за счет чего получается прирост производительности, если

при всех равных, если в Order By еще и сделать cast к int? Получается, что просто в этом случае планировщик не пробует индекс вообще использовать? И за счет этого в 10 раз быстрее происходит?

EXPLAIN SELECT * FROM test_1 WHERE (jdoc->'field1')::int <= 50000 ORDER BY (jdoc->'field1')::int DESC LIMIT 10;

27 ответов

11 просмотров

Скорее всего. ВПрочем, если внимательно прочитать explain -- то будет понятно за счёт чего.

выражения (в том числе касты) вырубают возможность использовать ключ для индексного поиска

Evgeniy- Автор вопроса
Ilya Anfimov
Скорее всего. ВПрочем, если внимательно прочитать ...

Ну кроме where, да, просто без Cast в Order By (просто с jpath, как в изначальном примере) тоже самое получается

Впрочем, у меня на таком запросе и вашых тэстовых данных никаких приростов не видно -- без ::int оно работает честные доли миллисекунды, с ним -- до секунды.

Evgeniy- Автор вопроса
Виктор Егоров
выражения (в том числе касты) вырубают возможность...

Понял принял, спасибо. А как-то вообще можно по jsonb полю сделать индекс типизированный (к примеру, я точно знаю, что в поле field1 у меня int) и хочу за это получить оптимизации по поиску и сортировке? Исходя из позиции того, что частые запросы будут именно сортировка с выборкой по этому полю. Или все-таки самый очевидный и правильный путь - это нормализовать данные и использовать композитный ключ и/или дополнительные индексы?

Evgeniy
Понял принял, спасибо. А как-то вообще можно по js...

лучше и правильнее — нормализовать. а так можно сделать функциональный индекс по выражению

Evgeniy- Автор вопроса
Виктор Егоров
лучше и правильнее — нормализовать. а так можно сд...

BTREE (((jdoc->'field1')::int)); - что-то вроде этого? Или все-таки custom function?

Evgeniy
BTREE (((jdoc->'field1')::int)); - что-то вроде эт...

как вам удобнее. если ф-ция, то её надо и в запросах использовать, иначе не проканает

Evgeniy- Автор вопроса
Виктор Егоров
как вам удобнее. если ф-ция, то её надо и в запрос...

Супер, спасибо. Можно еще один вопрос тоже по схожей теме?

Evgeniy
Понял принял, спасибо. А как-то вообще можно по js...

Можно. Так и делаешь, типизацыя это тожэ такая функцыя в итоге. И да, нормализовать данные -- это гораздо более правильный путь. У нас тут всё-таки не документоориентированная база, а реляцыонная.

Evgeniy- Автор вопроса
Виктор Егоров
как вам удобнее. если ф-ция, то её надо и в запрос...

Если коротко - то есть некие данные многие-ко-многим userId (text) —> segmentId (bigint) При проектировании таблицы было два варианта: 1. Composite Primary Key (userId, segmentId); 2. PK userId —> '{segments_array: []}'; 3. PK userId —> bigint[]; Условия: 1. Сегменты постоянно добавляются/удаляются у пользователей (индекс точно будет расти); 2. Поиск чаще всего будет происходить по UserId и Subset Of Segment Id (subset обычно небольшой относительно общего кол-ва сегментов); 3. Необходим обратный поиск всех userId по segmentId; В итоге пришел к 1 варианту - Composite PK. Нивелировать разреженность индекса планировал за счет fillfactor=90 и autovacuum_vacuum_scale_factor=0 с autovacuum_vacuum_threshold=20000. Однако на конференции (High Load) слышал, что люди зачастую делают JSONB (не структурированные данные) вроде как из-за того, чтобы индекс не получался фрагментированным (насколько я понял). Вот теперь вопрос - выстрелил ли я себе уже в ногу и если да, то какой все-таки вариант лучше выбрать? Пока до production код не дошел - могу менять как угодно и что угодно.

Evgeniy
Если коротко - то есть некие данные многие-ко-мног...

что значит “нивелировать разреженность индекса”? о чём речь?

Evgeniy- Автор вопроса
Виктор Егоров
что значит “нивелировать разреженность индекса”? о...

Возможно выражаюсь просто некорректно. В моем понимании, если я буду каждый раз удалять и добавлять значения в индексе - то будут образовываться пустоты в индексе (тут я немного плаваю ибо понахватался знаний из разных баз и уже немного каша в голове - я из мира MS Sql - больше опыта именно в нем и там было такое явления - что при удалении в индексе образуются "дырки" из-за которых деградация в скорости идет). Может я просто зря вообще об этом беспокоюсь - и все можно не париться и использовать как есть?

Evgeniy
Возможно выражаюсь просто некорректно. В моем пони...

от этого эффекта вы избавиться не сможете в любом случае. в 14-й версии индексы сильно лучше себя ведут в плане распухания. в целом — я бы не парился

Evgeniy
Если коротко - то есть некие данные многие-ко-мног...

Для поиска userid по segmentid ещё нужэн индэкс segmentid в таблицэ-связке. А так да, классическое решэние. Есть, конечно, всякие варианты организовать псевдо-column storage... Но в общем на самом деле это редко надо и редко помогает.

Evgeniy- Автор вопроса
Виктор Егоров
от этого эффекта вы избавиться не сможете в любом ...

Спасибо - если честно - то гора с плеч. Система обещает быть весьма нагруженной, и мне там нужны будут максимально быстрые запросы (понятно, что слой кеширования тоже будет)

Evgeniy
Возможно выражаюсь просто некорректно. В моем пони...

Да не особенно оно и будет распухать. Ну, то есть не большэ, чем остальная таблица, которую пылесосит vacuum...

Evgeniy- Автор вопроса
Ilya Anfimov
Для поиска userid по segmentid ещё нужэн индэкс se...

Да-да, индексы есть, даже больше - Foreign Keys сознательно не добавлены, т.к. тут консистентность будет решаться за счет клиента

Evgeniy
Спасибо - если честно - то гора с плеч. Система об...

вам тут сильно важно не допускать долгих транзакций. вплоть до принудительного ограничения времени запроса 5 минутами (к примеру). если нужны отчёты долгие и/или аналитика — либо отстающая, либо логическая реплика

Evgeniy
Да-да, индексы есть, даже больше - Foreign Keys со...

Тут, в общем типичный цыкл разработки -- придумать, чем можно проиндэксировать чтобы поиск по новым бизнес-требованиям не сканировал всю базу 100500 раз, потом ещё заставить postgres это использовать, чтобы планировщик всё не ломал и не сканировал 100500 раз, потом выкинуть старые индэксы, поскольку в новых размер индэксов ужэ в 10 раз большэ базы и вставка в 30 раз медленнее, чем была бы в одним primary key.

Evgeniy- Автор вопроса
Виктор Егоров
вам тут сильно важно не допускать долгих транзакци...

Ага, я поэтому update батчить собираюсь на клиенте в один поток в идеале - чтобы избежать как раз проблем с блокировками долгими. А на уровне базы/таблицы можно указывать max transaction time (или transaction timeout)? Или это только в клиентском коде?

Evgeniy- Автор вопроса
Ilya Anfimov
Тут, в общем типичный цыкл разработки -- придумать...

Ну надеюсь, что по 2 колонкам сильно много бизнес правил не придумают :) Тут скорее сервис для быстрой помощи агрегаций остальных сервисов, больше как персистентный словарь будет использоваться нежели, как источник полных данных. Пока что только как proof of concept - но в идеале должно быть сносным решением.

Evgeniy
Ага, я поэтому update батчить собираюсь на клиенте...

дело не в блокировках, точнее я не про них говорил. вам ничего не мешает гнать 10 потоков по 300 записей. и если оно всё не завязано на один общий счёт, к примеру, то будет нормально параллелиться. долгие транзакции тормозят вакуум, что приводит к распузанию таблиц и индексов. вы можете указать statement_timeout на уровне базы, тут не транзакция, а запрос. этот параметр можно выставить пользователю и/или базе конкретной. если нужна гибкость, то можно скрипт в крон повесить, который по pg_stat_activity будет отбирать нужные сессии и pg_terminate_backend()-ить их

Evgeniy
Ну надеюсь, что по 2 колонкам сильно много бизнес...

Можэт, тогда tarantool взять? Ну, то есть как бы всё выглядит что вам весь codebase постгреса с его традицыями хорошэй поддержки SQL, серверного программирования, типизацыи, надёжно отлажэнного ACID-версионника как-то не очень нужэн... А как тупая молотилка по одному-двум тупым индэксам -- это ну так себе СУБД, небыстрая.

Evgeniy- Автор вопроса
Виктор Егоров
дело не в блокировках, точнее я не про них говорил...

Вот это спасибо! Буду думать как лучше в своем кейсе применить.

Evgeniy- Автор вопроса
Ilya Anfimov
Можэт, тогда tarantool взять? Ну, то есть как бы в...

Уже в процессе - devops настраивает, но загрузка у них такая, что я в прод гораздо раньше выйду - так что пока что на имеющихся мощностях. Клиент будет на тарантул не сложно переписать (изначально заложено в архитектуру возможная смена DB)

Похожие вопросы

Обсуждают сегодня

Всем привет! Имеется функция: function IsValidChar(ch: UTF8Char): Boolean; var i: Integer; ValidChars: AnsiString; begin ValidChars := 'abcdefghijklmnopqrstuvwxyzABCDE...
Евгений
44
Чтобы перехватить все нажимания буков на форме, надо хук ставить? Пробовал на форме ОнКейДаун, оно ловит клаву если фокус не на компоненте с вводом текста
Serjone
15
лучше скажите, причём тут паскаль?
Alexey Kulakov
36
Всем привет! вывожу на общей стр дочерние ресурсыв каждом ресурсе галерея, и первая фотка должна выводиться на общей [!DocLister? &prepare=photo !]
Alekso
12
А можно вопрос? Мне сегодня сказали что у меня функция (которая просто заполняет массив значениями) не правильная void Full(double * arr, int n) { for (int i = 0; i < n; i...
† C E †
7
День добрый, подскажите пожалуйста, есть ли какой-то способ сказать ребару не компилировать определённое приложение? Всю доку их перечиатл ничего подобного не нашёл
Кирилл
14
Добрый вечер. Хочу чтобы у меня в классе поле было функцией, которая возвращает строку. Делаю так: interface ... TGetOutPath = function : String of object; ... protec...
Kirill Filippenok
12
Народ! Впервые клиенту пришло письмо от РКН, у вас, дескать, есть яндекс метрика, а нигде не написано, что вы ее юзаете. Никто не сталкивался?
Sasha Beep
10
Это может быть все-таки не флудвейт? у меня ботфазер принимает изменения и отображает даже что они изменились, на видео видно что он прислал якобы уже измененное описание, н...
OVERLINK
13
Здравствуйте, хочу сделать HelloWorld в консоли Дельфи, но функция API ничего не выводит, что я делаю не так? program Hello; {$APPTYPE CONSOLE} uses System.SysUtils, WinAPI.Wi...
Sergey Vinogradov
20
Карта сайта