Probabilmente non vuoi sentirlo, ma l'opzione migliore per accelerare SELECT DISTINCT
è evitare DISTINCT
di iniziare. In molti casi (non tutti!) Può essere evitato con una migliore progettazione del database o query migliori.
A volte, GROUP BY
è più veloce, perché richiede un percorso di codice diverso.
Nel tuo caso particolare , non sembra che tu possa sbarazzartene DISTINCT
. Ma potresti supportare la query con un indice specializzato se hai molte query di quel tipo:
CREATE INDEX foo ON events (project_id, "time", user_id);
L'aggiunta user_id
è utile solo se si ottengono scansioni solo indice da questo. Segui il link per i dettagli. Rimuoverebbe la costosa scansione di heap di Bitmap dal piano di query, che consuma il 90% del tempo di query.
Il tuo EXPLAIN
output mi dice che la query deve condensare 2.491 utenti distinti su mezzo milione di righe corrispondenti. Questo non diventerà super-veloce, non importa quello che fai, ma può essere sostanzialmente più veloce.
Se gli intervalli di tempo nelle tue query sono sempre gli stessi, un MATERIALIIZED VIEW
pieghevole user_id
per (project_id, <fixed time intervall>)
farebbe molta strada. Nessuna possibilità lì con intervalli di tempo variabili, però. Forse potresti almeno piegare gli utenti all'ora o qualche altra unità di tempo minimo, e questo acquisterebbe prestazioni sufficienti per giustificare il notevole sovraccarico.
Nitpick:
Molto probabilmente, i predicati su "time"
dovrebbero essere davvero:
AND "time" >= '2015-01-11 8:00:00'
AND "time" < '2015-02-10 8:00:00';
A parte:
non usare time
come identificatore. È una parola riservata in SQL standard e un tipo di base in Postgres.