Perbandingan kinerja antara menggunakan fungsi Join dan Window untuk mendapatkan nilai lead dan lag


11

Aku punya tabel dengan baris 20m, dan setiap baris memiliki 3 kolom: time, id, dan value. Untuk masing id- masing dan time, ada valueuntuk status. Saya ingin tahu nilai lead dan lag dari timeyang spesifik untuk yang spesifik id.

Saya telah menggunakan dua metode untuk mencapai ini. Salah satu metode menggunakan join dan metode lain menggunakan fungsi jendela lead / lag dengan indeks berkerumun di timedan id.

Saya membandingkan kinerja kedua metode ini dengan waktu eksekusi. Metode bergabung membutuhkan 16,3 detik dan metode fungsi jendela membutuhkan 20 detik, tidak termasuk waktu untuk membuat indeks. Ini mengejutkan saya karena fungsi jendela tampaknya maju sementara metode join adalah brute force.

Berikut adalah kode untuk dua metode:

Buat Indeks

create clustered index id_time
 on tab1 (id,time)

Bergabunglah dengan metode

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

Statistik IO dihasilkan dengan menggunakan SET STATISTICS TIME, IO ON:

Statistik untuk Metode Bergabung

Berikut adalah rencana eksekusi untuk metode bergabung

Metode Fungsi Jendela

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

(Memesan hanya dengan timemenghemat 0,5 detik.)

Berikut ini adalah rencana eksekusi untuk metode fungsi Window

Statistik IO

[Statistik untuk metode fungsi Jendela 4]


Saya memeriksa data sample_orig_month_1999dan sepertinya data mentah dipesan dengan baik oleh iddan time. Apakah ini alasan perbedaan kinerja?

Tampaknya metode gabungan memiliki lebih banyak bacaan logis daripada metode fungsi jendela, sedangkan waktu eksekusi untuk yang sebelumnya sebenarnya kurang. Apakah karena mantan memiliki paralelisme yang lebih baik?

Saya suka metode fungsi jendela karena kode ringkas, apakah ada cara untuk mempercepatnya untuk masalah khusus ini?

Saya menggunakan SQL Server 2016 pada Windows 10 64 bit.

Jawaban:


11

Kinerja mode baris LEADdan LAGfungsi jendela yang relatif rendah dibandingkan dengan self joins bukanlah hal baru. Sebagai contoh, Michael Zilberstein menulis tentang hal itu di SQLblog.com pada tahun 2012. Ada sedikit overhead dalam Segment (repeat)) Segment, Sequence Project, Window Spool, dan Stream Aggregate plan operator:

Bagian rencana

Di SQL Server 2016, Anda memiliki opsi baru, yaitu untuk mengaktifkan pemrosesan mode batch untuk agregat jendela. Ini memerlukan semacam indeks toko kolom di atas meja, bahkan jika itu kosong. Kehadiran indeks kolom toko saat ini diperlukan agar pengoptimal mempertimbangkan rencana mode kumpulan. Secara khusus, ini memungkinkan operator batch-mode Window Aggregate yang jauh lebih efisien.

Untuk menguji ini dalam kasus Anda, buat indeks penyimpanan kolom kosong yang tidak bercanda:

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

Kueri:

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;

Seharusnya sekarang berikan rencana eksekusi seperti:

Paket penyimpanan baris mode batch

... yang mungkin mengeksekusi lebih cepat.

Anda mungkin perlu menggunakan OPTION (MAXDOP 1)atau petunjuk lain untuk mendapatkan bentuk rencana yang sama saat menyimpan hasil dalam tabel baru. Versi paralel dari paket ini membutuhkan semacam mode batch (atau mungkin dua), yang mungkin sedikit lebih lambat. Ini lebih tergantung pada perangkat keras Anda.

Untuk lebih lanjut tentang operator Agregat Jendela Mode Batch, lihat artikel berikut oleh Itzik Ben-Gan:

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.