Вы, вероятно, не хотите слышать это, но лучший способ ускорить это 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.