Äußere Übernehmen-Links-Join-Leistung

37

Ich verwende SQL Server 2008 R2

Ich bin gerade auf APPLY in SQL gestoßen und fand es toll, wie es Abfrageprobleme in so vielen Fällen löst.

Viele der Tabellen, für die ich 2 Links-Joins verwendet habe, um das Ergebnis zu erhalten, konnten in 1 Outer-Apply-Tabelle verwendet werden.

Ich habe eine kleine Datenmenge in meinen lokalen DB-Tabellen und nach der Bereitstellung soll der Code auf Daten ausgeführt werden, die mindestens 20-mal so groß sind.

Ich befürchte, dass die äußere Anwendung für große Datenmengen länger dauern könnte als die beiden Bedingungen für Links-Joins.

Kann jemand sagen, wie genau gelten funktioniert und wie es die Leistung in sehr großen Daten auswirkt, wenn möglich einige proportionale Beziehungen mit der Größe jeder Tabelle wie proportional zu n1 ^ 1 oder n1 ^ 2 ... wobei n1 die Anzahl der Zeilen in der Tabelle ist 1.

Hier ist die Abfrage mit 2 Links Join

select EC.*,DPD.* from Table1 eC left join
  (
   select member_id,parent_gid,child_gid,LOB,group_gid,MAX(table2_sid) mdsid from Table2
   group by member_id,parent_gid,child_gid,LOB,group_gid

  ) DPD2 on DPD2.parent_gid = Ec.parent_gid
        AND DPD2.child_gid = EC.child_gid
        AND DPD2.member_id = EC.member_id
        AND DPD2.LOB = EC.default_lob
        AND DPD2.group_gid = EC.group_gid
  left join
  Table2 dpd on dpd.parent_gid = dpd2.parent_gid 
            and dpd.child_gid = dpd2.child_gid
            and dpd.member_id = dpd2.member_id 
            and dpd.group_gid = dpd2.group_gid 
            and dpd.LOB = dpd2.LOB
            and dpd.table2_sid = dpd2.mdsid

Hier ist die Abfrage mit Outer Apply

select * from Table1 ec   
OUTER APPLY (
      select top 1 grace_begin_date,retroactive_begin_date,Isretroactive
                    from Table2 DPD 
                    where DPD.parent_gid = Ec.parent_gid
                    AND DPD.child_gid = EC.child_gid
                    AND DPD.member_id = EC.member_id
                    AND DPD.LOB = EC.default_lob
                    AND DPD.group_gid = EC.group_gid
                    order by DPD.table2_sid desc
     ) DPD 
Pratyush Dhanuka
quelle

Antworten:

44

Kann mir jemand sagen, wie genau die Anwendung funktioniert und wie sich dies auf die Leistung bei sehr großen Datenmengen auswirkt

APPLYist ein korrelierter Join ( LATERAL JOINin einigen Produkten und neueren Versionen des SQL-Standards als a bezeichnet). Wie jede logische Konstruktion hat sie keinen direkten Einfluss auf die Leistung. Im Prinzip sollten wir in der Lage sein, eine Abfrage mit jeder logisch äquivalenten Syntax zu schreiben, und der Optimierer würde unsere Eingabe in genau denselben physischen Ausführungsplan umwandeln.

Dies würde natürlich erfordern, dass der Optimierer jede mögliche Transformation kennt und die Zeit hat, sich mit jeder einzelnen zu befassen. Dieser Prozess kann durchaus länger dauern als das derzeitige Zeitalter des Universums, sodass die meisten kommerziellen Produkte diesen Ansatz nicht verfolgen. Daher kann und hat die Abfragesyntax häufig einen Einfluss auf die endgültige Leistung, obwohl es schwierig ist, allgemeine Aussagen darüber zu treffen, was und warum besser ist.

Die spezifische Form von OUTER APPLY ( SELECT TOP ... )führt in aktuellen Versionen von SQL Server höchstwahrscheinlich zu einem Join mit korrelierten verschachtelten Schleifen, da das Optimierungsprogramm keine Logik zur Umwandlung dieses Musters in ein Äquivalent enthält JOIN. Der Join mit korrelierten verschachtelten Schleifen funktioniert möglicherweise nicht richtig, wenn die äußere Eingabe groß und die innere Eingabe nicht indiziert ist oder die benötigten Seiten nicht bereits im Speicher vorhanden sind. Aufgrund bestimmter Elemente des Kostenmodells des Optimierers ist es weniger wahrscheinlich JOIN, dass ein Join mit korrelierten verschachtelten Schleifen als ein semantisch identischer Join einen parallelen Ausführungsplan erzeugt.

Ich konnte die gleiche Abfrage mit einem einzelnen linken Join und row_number () durchführen.

Dies kann im allgemeinen Fall besser sein oder auch nicht. Sie müssen beide Alternativen mit repräsentativen Daten testen. Das LEFT JOINund hat ROW_NUMBERsicherlich das Potenzial, effizienter zu sein, aber es hängt von der genauen Form des gewählten Abfrageplans ab. Die wichtigsten Faktoren, die sich auf die Effizienz dieses Ansatzes auswirken, sind die Verfügbarkeit eines Indexes zur Abdeckung der erforderlichen Spalten und die Bereitstellung der für die Klauseln PARTITION BYund erforderlichen Reihenfolge ORDER BY. Ein zweiter Faktor ist die Größe der Tabelle. Eine effiziente und gut indizierte APPLYkann eine ROW_NUMBERmit optimaler Indizierung übertreffen, wenn die Abfrage einen relativ kleinen Teil der betreffenden Tabelle berührt. Testen ist erforderlich.

Paul White sagt GoFundMonica
quelle
2

Die erste Abfrage kann von nur einer Anforderung an SQL Server parallel ausgeführt werden. Es holt den gesamten Datensatz und gibt eine Ausgabe basierend auf Filterkriterien aus.

Im zweiten Fall wird es jedoch zeilenweise ausgeführt und für jede Zeile wird Tabelle2 gescannt und an das Ergebnis angehängt.

Wenn Ihre äußere Abfrage weniger Daten enthält, ist die zweite Abfrage besser (OUTER APPLY). Wenn die erste Abfrage jedoch mehr Daten enthält, sollten Sie die erste verwenden.

user55424
quelle