Sie möchten dies wahrscheinlich nicht hören, aber die beste Möglichkeit, die Geschwindigkeit zu erhöhen, SELECT DISTINCT
besteht darin, zunächst zu vermeiden DISTINCT
. In vielen Fällen (nicht allen!) Kann dies durch ein besseres Datenbank-Design oder bessere Abfragen vermieden werden.
Manchmal GROUP BY
ist es schneller, weil es einen anderen Codepfad benötigt.
In Ihrem speziellen Fall scheint es nicht so, als könnten Sie es loswerden DISTINCT
. Sie können die Abfrage jedoch mit einem speziellen Index unterstützen, wenn Sie viele Abfragen dieser Art haben:
CREATE INDEX foo ON events (project_id, "time", user_id);
Das Hinzufügen user_id
ist nur dann sinnvoll, wenn Sie nur Index-Scans erhalten . Folgen Sie dem Link für Details. Entfernt den teuren Bitmap-Heap-Scan aus Ihrem Abfrageplan, der 90% der Abfragezeit beansprucht.
Ihre EXPLAIN
Ausgabe sagt mir, dass die Abfrage 2.491 verschiedene Benutzer aus einer halben Million übereinstimmender Zeilen verdichten muss. Dies wird nicht superschnell, egal was Sie tun, aber es kann wesentlich schneller sein.
Wenn die Zeitintervalle in Ihren Abfragen immer gleich sind, würde eine MATERIALIIZED VIEW
Faltung user_id
pro (project_id, <fixed time intervall>)
viel bewirken. Keine Chance da mit unterschiedlichen Zeitintervallen. Möglicherweise könnten Sie die Anzahl der Benutzer pro Stunde oder eine andere Mindestzeiteinheit verringern, und dies würde genügend Leistung erbringen, um den erheblichen Mehraufwand zu rechtfertigen.
Nitpick:
Höchstwahrscheinlich sollten die Prädikate "time"
wirklich sein:
AND "time" >= '2015-01-11 8:00:00'
AND "time" < '2015-02-10 8:00:00';
Nebenbei:
Nicht time
als Bezeichner verwenden. Es ist ein reserviertes Wort in Standard-SQL und ein Basistyp in Postgres.