Вы, вероятно, не хотите слышать это, но лучший способ ускорить это SELECT DISTINCT
- избегать DISTINCT
с самого начала. Во многих случаях (не во всех!) Этого можно избежать с помощью лучшего дизайна базы данных или лучших запросов.
Иногда GROUP BY
это быстрее, потому что он использует другой путь кода.
В вашем конкретном случае это не похоже, что вы можете избавиться от DISTINCT
. Но вы можете поддержать запрос с помощью специализированного индекса, если у вас много запросов такого рода:
CREATE INDEX foo ON events (project_id, "time", user_id);
Добавление user_id
полезно только в том случае, если вы получаете только сканирование по индексу . Перейдите по ссылке для получения подробной информации. Удаляет дорогостоящее растровое сканирование кучи из вашего плана запросов, который потребляет 90% времени запроса.
Ваш EXPLAIN
вывод говорит мне, что запрос должен сгущать 2,491 различных пользователей из полумиллиона совпадающих строк. Это не станет очень быстрым, независимо от того, что вы делаете, но это может быть существенно быстрее.
Если временные интервалы в ваших запросах всегда одинаковы, MATERIALIIZED VIEW
сворачивание user_id
в (project_id, <fixed time intervall>)
большую сторону будет иметь большое значение. Там нет шансов с различными временными интервалами, хотя. Может быть, вы могли бы по крайней мере сбрасывать пользователей в час или какое-то другое минимальное время, и это купило бы производительность, достаточную для значительных накладных расходов.
Nitpick:
Скорее всего, предикаты "time"
должны быть:
AND "time" >= '2015-01-11 8:00:00'
AND "time" < '2015-02-10 8:00:00';
В сторону:
не используйте в time
качестве идентификатора. Это зарезервированное слово в стандартном SQL и базовый тип в Postgres.
Вот мой тест по делу Сэма и ответ Эрвина
Эрвин сказал: «Вы, вероятно, не хотите этого слышать, но лучший способ ускорить SELECT DISTINCT - это сначала избегать DISTINCT. Во многих случаях (не во всех!) Этого можно избежать с помощью лучшего проектирования базы данных или лучших запросов. " Я думаю, что он прав, мы должны избегать использования «различного, группового, упорядоченного по» (если есть).
Я встречался с ситуацией Сэма, и я думаю, что Сэм может использовать раздел таблицы событий по месяцам. Это уменьшит размер ваших данных при запросе, но вам нужна функция (pl / pgsql) для выполнения вместо запроса выше. Функция найдет соответствующие разделы (в зависимости от условий) для выполнения запроса.
источник