Olası satış ve gecikme değerleri elde etmek için Join ve Window işlevini kullanma arasındaki performans karşılaştırması


11

Ben 20M satırları olan bir tablo ve her bir sırada 3 sütun var time, idve value. Her biri için idve timebir orada valuestatü için. Belli bir kişi timeiçin belirli bir kişinin kurşun ve gecikme değerlerini bilmek istiyorum id.

Bunu başarmak için iki yöntem kullandım. Bir yöntem birleştirme yöntemini, bir diğer yöntem de timeve id.

Bu iki yöntemin performansını yürütme süresine göre karşılaştırdım. Join yöntemi 16.3 saniye sürer ve window işlevi yöntemi dizini oluşturma süresi dahil değil 20 saniye sürer. Bu beni şaşırttı çünkü birleştirme yöntemleri kaba kuvvetken pencere işlevi gelişmiş gibi görünüyor.

İki yöntemin kodu:

Dizin Oluştur

create clustered index id_time
 on tab1 (id,time)

Birleştirme yöntemi

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

IO istatistikleri kullanılarak oluşturulmuştur SET STATISTICS TIME, IO ON:

Birleştirme Yöntemi için İstatistik

Join yöntemi için yürütme planı

Pencere İşlev yöntemi

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

(Sipariş sadece time0,5 saniyedir.)

İşte Pencere işlev yöntemi için yürütme planı

ES istatistikleri

[Pencere fonksiyon yöntemi için istatistikler 4]


Verileri kontrol ettim ve sample_orig_month_1999ham verilerin idve tarafından sipariş edildiği görülüyor time. Performans farkının nedeni bu mu?

Join yönteminin pencere işlev yönteminden daha mantıklı okumalara sahip olduğu görülürken, birincisi için yürütme süresi aslında daha azdır. Birincisi daha iyi bir paralellik içerdiğinden mi?

Kısa kod nedeniyle pencere işlev yöntemini seviyorum, bu belirli sorun için hızlandırmak için herhangi bir yolu var mı?

SQL Server 2016'yı Windows 10 64 bit üzerinde kullanıyorum.

Yanıtlar:


11

Kendiliğinden birleşmelerle karşılaştırıldığında nispeten düşük satır modu performansı LEADve LAGpencere işlevleri yeni bir şey değildir. Örneğin, Michael Zilberstein 2012 yılında SQLblog.com'da bu konuda yazdı .

Plan bölümü

SQL Server 2016'da, pencere kümeleri için toplu iş modu işlemeyi etkinleştiren yeni bir seçeneğiniz vardır . Bu, boş olsa bile tabloda bir tür sütun mağazası dizini gerektirir. Optimize edicinin toplu iş modu planlarını dikkate alması için bir sütun deposu dizininin varlığı gereklidir. Özellikle, çok daha verimli Window Agregate toplu mod operatörünü etkinleştirir.

Bunu sizin durumunuzda test etmek için boş bir kümelenmemiş sütun mağaza dizini oluşturun:

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

Sorgu:

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;

Şimdi aşağıdaki gibi bir yürütme planı vermelidir:

Toplu mod satır mağaza planı

... çok daha hızlı çalışabilir.

OPTION (MAXDOP 1)Sonuçları yeni bir tabloda saklarken aynı plan şeklini elde etmek için bir veya başka ipucu kullanmanız gerekebilir . Planın paralel sürümü, biraz daha yavaş olabilen bir toplu iş modu sıralaması (veya muhtemelen iki) gerektirir. Daha çok donanımınıza bağlıdır.

Toplu İş Penceresi Toplama işleci hakkında daha fazla bilgi için Itzik Ben-Gan'ın aşağıdaki makalelerine bakın:

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.