Решение для ускорения медленного запроса SELECT DISTINCT в Postgres - PullRequest
24 голосов
/ 06 июля 2011

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

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

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

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

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

Ответы [ 3 ]

24 голосов
/ 06 июля 2011

Часто такие запросы можно ускорить, обойдя distinct, используя вместо этого group by:

select my_table.foo 
from my_table 
where [whatever where conditions you want]
group by foo;
15 голосов
/ 06 июля 2011

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

6 голосов
/ 08 июля 2011

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

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

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

...