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.
Hier ist mein Test zu Sams Fall und Erwins Antwort
Erwin sagte: "Das wollen Sie wahrscheinlich nicht hören, aber die beste Möglichkeit, SELECT DISTINCT zu beschleunigen, besteht darin, zunächst DISTINCT zu vermeiden. In vielen Fällen (nicht in allen Fällen!) Kann dies durch ein besseres Datenbankdesign oder bessere Abfragen vermieden werden ". Ich denke, er hat Recht, wir sollten vermeiden, "getrennt, gruppiert nach, geordnet nach" (falls vorhanden) zu verwenden.
Ich habe eine Situation wie in Sams Fall erlebt und ich denke, Sam kann die Partition für die Ereignistabelle monatlich verwenden. Es wird Ihre Datengröße reduzieren, wenn Sie abfragen, aber Sie benötigen eine Funktion (pl / pgsql), die anstelle der obigen Abfrage ausgeführt werden soll. Die Funktion findet geeignete Partitionen (abhängig von den Bedingungen), um die Abfrage auszuführen.
quelle