लीड और लैग मान प्राप्त करने के लिए Join and Window फ़ंक्शन का उपयोग करने के बीच प्रदर्शन तुलना


11

मैं 20M पंक्तियों के साथ एक मेज है, और प्रत्येक पंक्ति 3 स्तंभ हैं: time, id, और value। प्रत्येक के लिए idऔर time, valueस्थिति के लिए एक है । मैं timeएक विशिष्ट के लिए एक निश्चित के प्रमुख और अंतराल मूल्यों को जानना चाहता हूं id

मैंने इसे हासिल करने के लिए दो तरीकों का इस्तेमाल किया है। एक विधि जुड़ने का उपयोग कर रही है और दूसरी विधि विंडो फ़ंक्शन लीड / लैग का उपयोग क्लस्टर इंडेक्स के साथ timeऔर पर कर रही है id

मैंने निष्पादन समय द्वारा इन दोनों विधियों के प्रदर्शन की तुलना की। शामिल होने की विधि में 16.3 सेकंड लगते हैं और विंडो फ़ंक्शन विधि को सूचकांक बनाने के लिए समय सहित 20 सेकंड लगते हैं। इसने मुझे आश्चर्यचकित कर दिया क्योंकि विंडो फ़ंक्शन उन्नत प्रतीत होता है जबकि ज्वाइन मेथड्स ब्रूट फोर्स है।

यहाँ दो तरीकों के लिए कोड है:

सूचकांक बनाएँ

create clustered index id_time
 on tab1 (id,time)

विधि से जुड़ें

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 सांख्यिकी का उपयोग कर उत्पन्न SET STATISTICS TIME, IO ON:

जुड़ने की विधि के लिए आँकड़े

यहां शामिल होने की विधि के लिए निष्पादन योजना है

विंडो फंक्शन विधि

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

(केवल time0.5 सेकंड से ऑर्डर करना ।)

यहां विंडो फ़ंक्शन विधि के लिए निष्पादन योजना है

IO आँकड़े

[विंडो फ़ंक्शन विधि 4 के लिए आंकड़े]


मैंने डेटा की जाँच की sample_orig_month_1999और ऐसा लगता है कि कच्चे डेटा को अच्छी तरह से idऔर द्वारा आदेश दिया गया है time। क्या यह प्रदर्शन अंतर का कारण है?

ऐसा लगता है कि शामिल होने की विधि में विंडो फ़ंक्शन विधि की तुलना में अधिक तार्किक रीड हैं, जबकि पूर्व के लिए निष्पादन का समय वास्तव में कम है। यह क्योंकि पूर्व एक बेहतर समानांतरवाद है है?

संक्षिप्त कोड के कारण मुझे विंडो फ़ंक्शन विधि पसंद है, क्या इस विशिष्ट समस्या के लिए इसे गति देने का कोई तरीका है?

मैं विंडोज 10 64 बिट पर SQL सर्वर 2016 का उपयोग कर रहा हूं।

जवाबों:


11

सेल्फ जॉन्स की तुलना में अपेक्षाकृत कम रो-मोड प्रदर्शन LEADऔर LAGविंडो फ़ंक्शंस कोई नई बात नहीं है। उदाहरण के लिए, माइकल ज़िल्बर्स्टीन ने 2012 में SQLblog.com पर इसके बारे में लिखा था। (बार-बार) सेगमेंट, सीक्वेंस प्रोजेक्ट, विंडो स्पूल और स्ट्रीम एग्रीगेट प्लान ऑपरेटरों में बहुत अधिक ओवरहेड है:

योजना अनुभाग

SQL Server 2016 में, आपके पास एक नया विकल्प है, जो विंडो एग्रीगेट के लिए बैच मोड प्रोसेसिंग को सक्षम करने के लिए है । यह टेबल पर किसी प्रकार के कॉलमस्टोर इंडेक्स की आवश्यकता है, भले ही वह खाली हो। वर्तमान में बैच मोड योजनाओं पर विचार करने के लिए अनुकूलक के लिए एक कॉलमस्टोर इंडेक्स की उपस्थिति आवश्यक है। विशेष रूप से, यह बहुत अधिक कुशल विंडो एग्रीगेट बैच-मोड ऑपरेटर को सक्षम करता है।

अपने मामले में इसका परीक्षण करने के लिए, एक खाली नॉनस्टस्टर्ड कॉलमस्टोर इंडेक्स बनाएं:

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

पूछताछ:

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;

अब एक निष्पादन योजना देना चाहिए जैसे:

बैच मोड पंक्ति स्टोर योजना

... जो अच्छी तरह से बहुत तेजी से निष्पादित कर सकता है।

OPTION (MAXDOP 1)नई तालिका में परिणाम संग्रहीत करते समय आपको एक ही योजना आकार प्राप्त करने के लिए या किसी अन्य संकेत का उपयोग करने की आवश्यकता हो सकती है । योजना के समानांतर संस्करण के लिए एक बैच मोड सॉर्ट (या संभवतः दो) की आवश्यकता होती है, जो थोड़ा धीमा हो सकता है। यह बल्कि आपके हार्डवेयर पर निर्भर करता है।

बैच मोड विंडो सकल ऑपरेटर के बारे में अधिक के लिए, Itzik बेन-गण द्वारा निम्न लेख देखें:

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.