Alternative zur SQL-Unterabfrage

8

Ich habe die folgende Frage:

%Vor%

Hier ist erklären Sie analysieren Ausgabe der obigen Abfrage.

Die Abfrage wurde ordnungsgemäß ausgeführt, bis ich die folgende Anzahl Unterabfrage hinzugefügt habe:

%Vor%

Tatsächlich habe ich einfachere Unterabfragen versucht und es scheint die Aggregatfunktion selbst zu sein, die sich die Zeit nimmt.

Ist das ein alternativer Weg, um die Zähler-Unterabfrage an jedes Ergebnis anzuhängen? Sollte ich die Ergebnisse nach der ersten Abfrage aktualisieren?

Hier ist ein pastebin , der die Tabelle erstellt und am Ende die schlecht durchzuführende Abfrage ausführt, um anzuzeigen, wie die Ausgabe aussehen soll.

    
dagda1 09.05.2014, 12:39
quelle

4 Antworten

3

Wenn Sie die Antwort von Paul Guyot erweitern, können Sie die Unterabfrage in eine abgeleitete Tabelle verschieben, die schneller ausgeführt werden sollte, da sie die Nachrichtenanzahl in einem Scan (plus Join) im Gegensatz zu einem Scan pro Zeile abruft.

%Vor%

Fiedel mit Pastebin-Daten - Ссылка

Im Folgenden sind die Abfragepläne aufgeführt, die postgres für das Abrufen der Anzahl in einer korrelierten Unterabfrage und das Abrufen der Anzahl durch Abrufen einer abgeleiteten Tabelle erstellt. Ich habe einen meiner eigenen Tische benutzt, aber ich denke, die Ergebnisse sollten ähnlich sein.

Korrelierte Unterabfrage

%Vor%

Einer abgeleiteten Tabelle beitreten

%Vor%     
FuzzyTree 27.05.2014, 09:30
quelle
3

Nach dem, was ich von der Semantik Ihrer Abfrage verstehe, können Sie vereinfachen:

%Vor%

zu:

%Vor%

Tatsächlich ist message_id nicht unbedingt eindeutig, aber wenn Sie für einen gegebenen Wert von message_id eindeutige Zeilen haben, schlägt Ihre Abfrage fehl.

Diese Vereinfachung ändert jedoch die Kosten der Abfrage nicht wesentlich. In der Tat besteht das Problem hier darin, dass Sie zwei vollständige Scans von Tabellen-E-Mails benötigen, um die Abfrage auszuführen (sowie einen Index-Scan auf emails_message_id_index). Sie können einen vollständigen Scan speichern, indem Sie einen Index für das Referenz-Array verwenden.

Sie erstellen einen solchen Index mit:

%Vor%

Der Index allein hilft der anfänglichen Abfrage erheblich: Vorausgesetzt, es gibt aktuelle Statistiken, wie bei einer ausreichend großen Anzahl von Zeilen, führt PostgreSQL einen Index-Scan durch. Sie sollten die Unterabfrage jedoch wie folgt ändern, um dem Planer zu helfen, einen Bitmap-Index-Scan für diesen Array-Index durchzuführen:

%Vor%

Die letzte Abfrage würde lauten:

%Vor%

Um die erwarteten Gewinne zu veranschaulichen, wurden einige Tests in einer Dummy-Umgebung durchgeführt:

  • mit 10.000 Zeilen in Tabellen-E-Mails (und entsprechenden Zeilen in Tabelle email_participants), erste Abfrage in 787 ms, mit dem Index-Scan fällt dies auf 399 ms und die vorgeschlagene Abfrage läuft in 12ms;
  • mit 100.000 Zeilen beginnt die Abfrage in 9.200ms, mit dem Index-Scan fällt dieser auf 4.251ms und die vorgeschlagene Abfrage läuft in 637ms.
Paul Guyot 21.05.2014 22:33
quelle
2

Es ist nicht einfach, das ohne Testdaten richtig zu machen

%Vor%

Der Grund für die langsame Abfrage ist, dass Sie für jede Zeile Ihrer Ergebnismenge eine Tabelle oder eine Indexsuche durchführen. Das nennt man eine korrelierte Unterabfrage.

Die group by 1, 2,... ist nur eine kurze Hand für die Spaltennamen in der Auswahlliste.

Die Umwandlung von boolesch in Ganzzahl ergibt 1 oder 0.

    
Clodoaldo Neto 09.05.2014 13:28
quelle
0

Ich habe Ihre Anfrage im Pastebin als Ausgangspunkt verwendet. Dies unterscheidet sich von dem hier geposteten dadurch, dass es der Tabelle email_participants nicht beitritt.

Ich glaube, es kann so einfach sein (oder habe ich etwas vermisst?):

%Vor%     
wvdz 21.05.2014 19:04
quelle

Tags und Links