it-swarm.com.de

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

Ich habe eine Tabelle mit 20 Millionen Zeilen und jede Zeile hat 3 Spalten: time, id und value. Für jedes id und time gibt es ein value für den Status. Ich möchte die Lead- und Lag-Werte eines bestimmten time für ein bestimmtes id kennen.

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 für time und 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

Mit SET STATISTICS TIME, IO ON:

(Statistics for Join Method

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

(Die Bestellung nur mit time spart 0,5 Sekunden.)

Hier ist der Ausführungsplan für Fensterfunktionsmethode

E/A-Statistiken

[Statistics for Window function method 4]


Ich habe die Daten in sample_orig_month_1999 und es scheint, dass die Rohdaten nach id und time gut geordnet sind. 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.

10
Jason

Die relativ geringe Leistung der Fensterfunktionen LEAD und LAG im Zeilenmodus im Vergleich zu Self-Joins ist nichts Neues. Zum Beispiel Michael Zilberstein schrieb darüber auf SQLblog.com im Jahr 2012. Die Operatoren für (wiederholte) Segment-, Sequenzprojekt-, Fensterspool- und Stream-Aggregat-Pläne sind mit einem erheblichen Aufwand verbunden:

(Plan section

In SQL Server 2016 haben Sie eine neue Option, nämlich Stapelverarbeitung für die Fensteraggregate zu aktivieren. 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:

(Batch mode row store plan

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

Möglicherweise müssen Sie ein 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:

11
Paul White 9