USING-Konstrukt in JOIN-Klausel kann in bestimmten Fällen Optimierungsbarrieren einführen?

35

Ich wurde darauf aufmerksam gemacht, dass das USINGKonstrukt (anstelle von ON) in der FROMKlausel von SELECTAbfragen in bestimmten Fällen Optimierungsbarrieren einführen kann.

Ich meine dieses Schlüsselwort:

WÄHLEN *
Von einem
JOIN b USING (a_id)

Nur in komplexeren Fällen.

Kontext: dieser Kommentar zu dieser Frage .

Ich benutze dies oft und habe bisher noch nichts bemerkt. Ich wäre sehr an einem Testfall interessiert , der den Effekt demonstriert, oder an Links zu weiteren Informationen. Meine Suchanstrengungen blieben leer.

Die perfekte Antwort wäre ein Testfall USING (a_id)mit schlechterer Leistung im Vergleich zur alternativen Join-Klausel ON a.a_id = b.a_id- ob dies tatsächlich passieren kann.

Erwin Brandstetter
quelle
2
@kgrittn: Das habe ich bisher allgemein erwartet: Das USINGgeht etwas schneller, da es in der Ergebnismatrix eine Spalte weniger gibt. Ihre Ergebnisse stammen aus den Jahren 2005 und 2008. Ich gehe davon aus, dass alle Probleme inzwischen behoben wurden. Allerdings kann ich eine mögliche Einschränkung sehen: Verknüpft mit USINGmuß möglicherweise werden angewandt , um , wie die resultierenden Joinspalte ein gemeinsames Produkt ist. Dadurch werden die Optionen bei der Neuordnung von JOINs möglicherweise eingeschränkt.
Erwin Brandstetter
1
Ich habe diesen Thread gefunden, der möglicherweise damit zu tun hat, dass ich ihn nicht mehr so ​​oft verwendet habe, da eine VIEW mit einer USING-Bedingung für einen Join Probleme beim Dump / Restore verursachen kann: archives.postgresql.org/pgsql- bugs / 2011-06 / msg00030.php Ich habe immer noch das nörgelnde Gefühl, dass es einen anderen Thread gab, der sich auf Leistungsprobleme bei der Verwendung von USING bezog. Es ist wahrscheinlich sicher, es außerhalb von Ansichten zu verwenden, und denken Sie daran, stattdessen ON als Diagnoseschritt zu versuchen, wenn eine Abfrage langsam ist.
Kgrittn
1
Es sieht so aus, als würde "using" den Code ein wenig lesbar machen, aber ich vermute, dass beide Felder den gleichen Namen benötigen. Ich denke nicht, dass mit eine bessere Leistung erzielt wird als mit einem "Ein", da die DB sowieso das Match machen muss, es ist wie wenn ein Select die gleiche Leistung hat wie ein Join (korrigiere mich, wenn ich mich irre), der Der Unterschied besteht darin, dass Join sauberer und leichter zu warten ist.
jcho360
2
@HLGEM: Es ist nur ein symbolischer Name und bei nur zwei Tabellen, wie in meinem Beispiel, gibt es keinen Raum für Verwirrung. Trotzdem habe ich die Frage geändert. Würde die unglückliche Verwendung von idals Spaltenname nicht fördern wollen .
Erwin Brandstetter
2
@ChristiaanWesterbeek: Ich bin anderer Meinung. Die "Anlaufstelle" für eingehende Postgres-Antworten ist (noch) das Mailing. Nur sehr wenige Postgres-Entwickler sind auf SO aktiv, aber alle Postgres-Entwickler und Experten lesen die Mailingliste
a_horse_with_no_name 23.04.18

Antworten:

12

Erwin: Ich stimme mit der Idee überein, dass die Verwendung starrer Ordnungen durchaus viele Randfälle schaffen könnte, in denen optimale Pläne ausgeschlossen wären. Ich habe kürzlich jemandem geholfen, der so etwas in seiner Anfrage hatte:

LEFT JOIN ( 
     a 
     JOIN b ON a.id = b.a_id
     JOIN c ON b.c_id = c.id
) ON a.id = something.a_id
LEFT JOIN (
     table1 t1
     JOIN table2 t2 ON t1.some_field = t2.other_field
     JOIN talbe3 t3 ON t2.yafield = t3.something_else
) ON ....
repeat a few more times

In seinem Fall verursachte der schlimmste dieser Join-Blöcke einen Nested-Loop-Join durch etwa 200.000 Zeilen, etwa 20.000 Mal (rechnen Sie nach), und da die Schlüssel nicht in Indizes verschoben werden konnten, war dies ein sequentieller Scan. Dies bedeutete, dass die Gesamtabfrage aufgrund kaskadierender Planänderungen ca. 3 Stunden dauerte. Durch die Verteilung des linken Joins konnten die Tasten gedrückt werden und die Abfrage wurde in wenigen Sekunden ausgeführt. Natürlich ist dies nicht genau gleichbedeutend, weshalb der Planer sie nicht als gleichwertig behandeln kann. Daher wurde dieser Plan nicht als Hash-Join interpretiert und anschließend eine verschachtelte Schleife ausgeführt, die schmerzhaft langsam war.

Jedes Mal, wenn Sie die Verknüpfungen in einer bestimmten Reihenfolge erzwingen, führen Sie Fälle ein, in denen möglicherweise noch keine wichtigen Filterinformationen für die Ausführung des Plans verfügbar sind, und damit, was möglicherweise später in einer schnellen Indexsuche / Hashverknüpfung möglich ist Möglicherweise müssen Sie in einer verschachtelten Schleife / einem sequentiellen Scan viel langsamer vorgehen. Das obige Fragment ist zwar nicht sofort äquivalent, weist jedoch dasselbe Problem auf.

Chris Travers
quelle