PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Warum die natürlichste Abfrage (dh die Verwendung von INNER JOIN (anstelle von LEFT JOIN)) sehr langsam ist

(Wie angegeben, füge ich einen Teil meines Kommentars in eine Antwort ein, da das Problem gelöst wurde)

Wandeln Sie die EXISTS-Ausdrücke in IN-Ausdrücke um.

Dies funktioniert in diesem Fall besser, da die Abfrage jetzt effektiv von „innen und außen“ ausgewertet wird, beginnend mit der Abfrage, die Ihren stärksten einschränkenden Faktor enthält:die Volltextsuche. Diese Abfrage gibt einen kleinen Satz von Zeilen zurück, die direkt mit dem Primärschlüssel der äußeren Abfrage (WHERE x in (SELECT X...)) verglichen werden können, anstatt die "innere" Abfrage einmal pro Wert von aufzurufen die äußere Abfrage (oder für alle Werte in Ihrem ursprünglichen Fall, wenn ich es richtig lese). Die EXISTS-Methode führt hier zu verschachtelten Schleifen (eine Auswertung einer Abfrage für jeden Wert in einer anderen) im Vergleich zur IN-Methode, die Hash-Joins verwendet (in vielen, wenn nicht den meisten Fällen eine viel effizientere Ausführungsmethode.

Beachten Sie, dass es bei der EXISTS-Methode vier verschachtelte Schleifen gibt, die jeweils mindestens 3.000 Mal ausgeführt werden. Diese Kosten summieren sich. Obwohl es sich nicht um einen direkten Vergleich handelt, können Sie verschachtelte Schleifen wie FOR-Schleifen im Anwendungscode behandeln:Jedes Mal, wenn Sie eine innere Schleife aufrufen, steigt Ihre Big-O-Schätzung um eine Größenordnung:O(n) bis O(n^). 2) zu O(n^3) usw.

Hash Join ähnelt eher einer Karte, bei der zwei Arrays gleichzeitig durchlaufen werden und eine Operation für beide ausgeführt wird. Dies ist ungefähr linear (O(n)). Stellen Sie sich diese als additiv verschachtelt vor, sodass sie von O(n) zu O(2n) zu O(3n) usw. gehen würden.

Ja, ja, ich weiß, es ist nicht ganz dasselbe, aber der Punkt ist, dass mehrere verschachtelte Schleifen normalerweise auf einen langsamen Abfrageplan hindeuten und der Vergleich der beiden Big-O-Stile die Erkennung erleichtert, glaube ich.

Verschachtelte Schleifen und EXISTS sind an sich nichts Böses, aber für die meisten Fälle, in denen es eine grundlegende Filterbedingung gibt, die letztendlich alles beeinflusst (z. B. die Volltextsuche in der Frage), einen IN-Ausdruck (oder in einigen Fälle, ein richtiger JOIN) ergibt einen viel effizienteren Plan.