Probablemente no quiera escuchar esto, pero la mejor opción para acelerar SELECT DISTINCT
es evitar DISTINCT
comenzar. En muchos casos (¡no en todos!) Se puede evitar con un mejor diseño de la base de datos o mejores consultas.
A veces, GROUP BY
es más rápido, porque toma una ruta de código diferente.
En su caso particular , no parece que pueda deshacerse de él DISTINCT
. Pero podría admitir la consulta con un índice especializado si tiene muchas consultas de ese tipo:
CREATE INDEX foo ON events (project_id, "time", user_id);
Agregar user_id
solo es útil si obtiene escaneos de solo índice de esto. Sigue el enlace para más detalles. Eliminaría el costoso análisis de montón de mapa de bits de su plan de consulta, que consume el 90% del tiempo de consulta.
Su EXPLAIN
resultado me dice que la consulta tiene que condensar 2.491 usuarios distintos de medio millón de filas coincidentes. Esto no se volverá súper rápido, sin importar lo que haga, pero puede ser sustancialmente más rápido.
Si los intervalos de tiempo en sus consultas son siempre los mismos, un MATERIALIIZED VIEW
plegado user_id
por cada vez (project_id, <fixed time intervall>)
sería de gran ayuda. Sin embargo, no hay posibilidades con intervalos de tiempo variables. Quizás al menos podría doblar a los usuarios por hora o alguna otra unidad de tiempo mínima, y eso compraría suficiente rendimiento para garantizar la considerable sobrecarga.
Nitpick:
Muy probablemente, los predicados en "time"
realidad deberían ser:
AND "time" >= '2015-01-11 8:00:00'
AND "time" < '2015-02-10 8:00:00';
Aparte:
no utilizar time
como identificador. Es una palabra reservada en SQL estándar y un tipo básico en Postgres.