Подтвердить что ты не робот

Решение для ускорения медленного запроса SELECT DISTINCT в Postgres

Запрос в основном:

SELECT DISTINCT "my_table"."foo" from "my_table" WHERE...

Притворившись, что я на 100% уверен, что часть запроса DISTINCT является причиной, по которой она выполняется медленно, я пропустил остальную часть запроса, чтобы избежать путаницы, поскольку это явная часть медлительности, в первую очередь связанных с (различный всегда источник медленности).

В рассматриваемой таблице имеется 2,5 миллиона строк данных. DISTINCT необходим для целей, которые не перечислены здесь (потому что я не хочу возвращать измененный запрос, а скорее просто общая информация о том, как различные запросы выполняются быстрее на уровне СУБД, если это возможно).

Как я могу сделать DISTINCT быстрее работать (используя Postgres 9, в частности), не изменяя SQL (т.е. я не могу изменить этот SQL-вход, но иметь доступ к оптимизации чего-то на уровне DB)?

4b9b3361

Ответ 1

Ваш DISTINCT вызывает сортировку выходных строк, чтобы найти дубликаты. Если вы поместите индекс в столбцы (столбцы), выбранные по запросу, база данных сможет считывать их в порядке индекса и сохранять шаг сортировки. Многое будет зависеть от деталей запроса и используемых таблиц. Ваше высказывание "знаете, что проблема с DISTINCT" действительно ограничивает объем доступных ответов.

Ответ 2

Зачастую вы можете запускать такие запросы быстрее, работая вокруг distinct, используя вместо этого group by:

select my_table.foo 
from my_table 
where [whatever where conditions you want]
group by foo;

Ответ 3

Вы можете попробовать увеличить параметр work_mem, в зависимости от размера вашего набора данных. Это может привести к переключению плана запроса на агрегаты хэша, которые обычно бывают быстрее.

Но прежде чем устанавливать его слишком высоко в глобальном масштабе, сначала прочитайте его. Вы можете легко взорвать свой сервер, потому что параметр max_connections действует как множитель для этого числа.

Это означает, что если вы должны установить work_mem = 128MB, и вы установите max_connections = 100 (по умолчанию), вы должны иметь более 12,8 ГБ ОЗУ. Вы, по сути, говорите серверу, что он может так много использовать для выполнения запросов (даже не рассматривая другое использование памяти Postgres или иначе).