Leistungsvergleich zwischen der Verwendung der Join- und Window-Funktion zum Abrufen von Lead- und Lag-Werten


10

Ich habe eine Tabelle mit 20 M Zeilen und jede Zeile besteht aus 3 Säulen: time, id, und value. Für jedes idund timegibt es ein valuefür den Status. Ich möchte die Lead- und Lag-Werte eines bestimmten timefür einen bestimmten kennen id.

Ich habe zwei Methoden angewendet, um dies zu erreichen. Eine Methode verwendet Join und eine andere Methode verwendet die Fensterfunktionen Lead / Lag mit Clustered Index auf timeund id.

Ich habe die Leistung dieser beiden Methoden nach Ausführungszeit verglichen. Die Join-Methode dauert 16,3 Sekunden und die Fensterfunktionsmethode dauert 20 Sekunden, ohne die Zeit zum Erstellen des Index. Das hat mich überrascht, weil die Fensterfunktion erweitert zu sein scheint, während die Join-Methoden Brute Force sind.

Hier ist der Code für die beiden Methoden:

Index erstellen

create clustered index id_time
 on tab1 (id,time)

Join-Methode

select a1.id,a1.time
   a1.value as value, 
   b1.value as value_lag,
   c1.value as value_lead
into tab2
from tab1 a1
left join tab1 b1
on a1.id = b1.id
and a1.time-1= b1.time
left join tab1 c1
on a1.id = c1.id
and a1.time+1 = c1.time

E / A-Statistiken generiert mit SET STATISTICS TIME, IO ON:

Statistiken für die Join-Methode

Hier ist der Ausführungsplan für die Join-Methode

Fenster Funktionsmethode

select id, time, value, 
   lag(value,1) over(partition by id order by id,time) as value_lag,
   lead(value,1) over(partition by id order by id,time) as value_lead
into tab2
from tab1

(Bestellung nur mit timespart 0,5 Sekunden.)

Hier ist der Ausführungsplan für die Fensterfunktionsmethode

E / A-Statistiken

[Statistik für Fensterfunktionsmethode 4]


Ich habe die Daten eingecheckt sample_orig_month_1999und es scheint, dass die Rohdaten von idund gut geordnet sind time. Ist dies der Grund für Leistungsunterschiede?

Es scheint, dass die Join-Methode mehr logische Lesevorgänge aufweist als die Fensterfunktionsmethode, während die Ausführungszeit für die erstere tatsächlich kürzer ist. Liegt es daran, dass Ersteres eine bessere Parallelität hat?

Ich mag die Fensterfunktionsmethode wegen des prägnanten Codes. Gibt es eine Möglichkeit, sie für dieses spezielle Problem zu beschleunigen?

Ich verwende SQL Server 2016 unter Windows 10 64-Bit.

Antworten:


11

Die im Vergleich zu Self-Joins relativ geringe Leistung von Zeilen- LEADund LAGFensterfunktionen im Zeilenmodus ist nichts Neues. Zum Beispiel Michael Zilberstein schrieb darüber auf SQLblog.com im Jahr 2012 zurück Es ist ziemlich viel Aufwand in die (wiederholt) Segment, Sequenz Projekt, Fenster Spool und Stream - Aggregate Plan Betreiber:

Abschnitt planen

In SQL Server 2016 haben Sie eine neue Option, mit der Sie die Stapelmodusverarbeitung für die Fensteraggregate aktivieren können . Dies erfordert eine Art Spaltenspeicherindex für die Tabelle, auch wenn diese leer ist. Das Vorhandensein eines Columnstore-Index ist derzeit erforderlich, damit der Optimierer Stapelmoduspläne berücksichtigen kann. Insbesondere ermöglicht es den wesentlich effizienteren Batch-Modus-Operator für Fensteraggregate.

Um dies in Ihrem Fall zu testen, erstellen Sie einen leeren nicht gruppierten Columnstore-Index:

 -- Empty CS index
CREATE NONCLUSTERED COLUMNSTORE INDEX dummy 
ON dbo.tab1 (id, [time], [value]) 
WHERE id < 0 AND id > 0;

Die Abfrage:

SELECT
    T1.id,
    T1.[time],
    T1.[value],
    value_lag = 
        LAG(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time]),
    value_lead =
        LEAD(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time])
FROM dbo.tab1 AS T1;

Sollte jetzt einen Ausführungsplan geben wie:

Zeilenspeicherplan im Stapelmodus

... die möglicherweise viel schneller ausgeführt werden.

Möglicherweise müssen Sie einen OPTION (MAXDOP 1)oder einen anderen Hinweis verwenden, um die gleiche Planform zu erhalten, wenn Sie die Ergebnisse in einer neuen Tabelle speichern. Die parallele Version des Plans erfordert eine Stapelmodus-Sortierung (oder möglicherweise zwei), die möglicherweise etwas langsamer ist. Es hängt eher von Ihrer Hardware ab.

Weitere Informationen zum Aggregat-Operator für Stapelmodusfenster finden Sie in den folgenden Artikeln von Itzik Ben-Gan:

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.