एक अस्थायी स्पूल की तुलना में टेम्बी टेबल हेलोवीन समस्या का अधिक कुशल समाधान क्यों है?


14

निम्न तालिका पर विचार करें जो किसी स्रोत तालिका से पंक्तियाँ सम्मिलित करती हैं यदि वे लक्ष्य तालिका में पहले से नहीं हैं:

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
    SELECT 1
    FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
    WHERE maybe_new_rows.ID = halloween.ID
)
OPTION (MAXDOP 1, QUERYTRACEON 7470);

एक संभव योजना आकार में एक मर्ज जॉइन और एक उत्सुक स्पूल शामिल हैं। हैलोवीन की समस्या को हल करने के लिए उत्सुक स्पूल ऑपरेटर मौजूद है :

पहली योजना

मेरी मशीन पर, उपरोक्त कोड लगभग 6900 एमएस में निष्पादित होता है। तालिकाओं को बनाने के लिए रिप्रो कोड प्रश्न के निचले भाग में शामिल है। अगर मैं प्रदर्शन से असंतुष्ट हूं तो मैं उत्सुक स्पूल पर भरोसा करने के बजाय एक अस्थायी तालिका में सम्मिलित की जाने वाली पंक्तियों को लोड करने का प्रयास कर सकता हूं। यहाँ एक संभव कार्यान्वयन है:

DROP TABLE IF EXISTS #CONSULTANT_RECOMMENDED_TEMP_TABLE;
CREATE TABLE #CONSULTANT_RECOMMENDED_TEMP_TABLE (
    ID BIGINT,
    PRIMARY KEY (ID)
);

INSERT INTO #CONSULTANT_RECOMMENDED_TEMP_TABLE WITH (TABLOCK)
SELECT maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
    SELECT 1
    FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
    WHERE maybe_new_rows.ID = halloween.ID
)
OPTION (MAXDOP 1, QUERYTRACEON 7470);

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT new_rows.ID
FROM #CONSULTANT_RECOMMENDED_TEMP_TABLE new_rows
OPTION (MAXDOP 1);

नया कोड लगभग 4400 एमएस में निष्पादित होता है। मैं वास्तविक योजनाएं प्राप्त कर सकता हूं और वास्तविक समय सांख्यिकी ™ का उपयोग करके जांच कर सकता हूं कि ऑपरेटर स्तर पर समय कहां खर्च किया गया है। ध्यान दें कि वास्तविक योजना के लिए पूछना इन प्रश्नों के लिए महत्वपूर्ण ओवरहेड जोड़ता है ताकि योग पिछले परिणामों से मेल नहीं खाएंगे।

╔═════════════╦═════════════╦══════════════╗
  operator    first query  second query 
╠═════════════╬═════════════╬══════════════╣
 big scan     1771         1744         
 little scan  163          166          
 sort         531          530          
 merge join   709          669          
 spool        3202         N/A          
 temp insert  N/A          422          
 temp scan    N/A          187          
 insert       3122         1545         
╚═════════════╩═════════════╩══════════════╝

उत्सुक स्पूल के साथ क्वेरी प्लान टेम्पर टेबल का उपयोग करने वाली योजना की तुलना में इंसर्ट और स्पूल ऑपरेटरों पर अधिक समय बिताने के लिए लगता है।

टेम्प टेबल के साथ योजना अधिक कुशल क्यों है? वैसे भी एक उत्सुक स्पूल सिर्फ एक आंतरिक अस्थायी तालिका नहीं है? मेरा मानना ​​है कि मैं उन जवाबों की तलाश में हूं जो इंटर्नल पर ध्यान केंद्रित करते हैं। मैं यह देखने में सक्षम हूं कि कॉल स्टैक अलग कैसे हैं लेकिन बड़ी तस्वीर का पता नहीं लगा सकते।

यदि कोई जानना चाहता है तो मैं SQL Server 2017 CU 11 पर हूं। उपरोक्त प्रश्नों में प्रयुक्त तालिकाओं को आबाद करने के लिए कोड है:

DROP TABLE IF EXISTS dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR;

CREATE TABLE dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR (
ID BIGINT NOT NULL,
PRIMARY KEY (ID)
);

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT TOP (20000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
CROSS JOIN master..spt_values t3
OPTION (MAXDOP 1);


DROP TABLE IF EXISTS dbo.A_HEAP_OF_MOSTLY_NEW_ROWS;

CREATE TABLE dbo.A_HEAP_OF_MOSTLY_NEW_ROWS (
ID BIGINT NOT NULL
);

INSERT INTO dbo.A_HEAP_OF_MOSTLY_NEW_ROWS WITH (TABLOCK)
SELECT TOP (1900000) 19999999 + ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

जवाबों:


14

इसे मैं मैनुअल हैलोवीन प्रोटेक्शन कहता हूं ।

आप इसे अपने लेख में एक अद्यतन बयान के साथ इस्तेमाल किया जा रहा का एक उदाहरण मिल सकता है अनुकूलन अद्यतन प्रश्नों । एक ही शब्दार्थ को संरक्षित करने के लिए थोड़ा सावधान रहना होगा, उदाहरण के लिए, सभी समवर्ती संशोधनों के खिलाफ लक्ष्य तालिका को लॉक करके, जबकि अलग-अलग प्रश्न निष्पादित होते हैं, यदि यह आपके परिदृश्य में प्रासंगिक है।

टेम्प टेबल के साथ योजना अधिक कुशल क्यों है? एक उत्सुक स्पूल ज्यादातर सिर्फ एक आंतरिक अस्थायी तालिका नहीं है?

एक स्पूल में एक अस्थायी तालिका की कुछ विशेषताएं हैं, लेकिन दो सटीक समकक्ष नहीं हैं। विशेष रूप से, स्पूल अनिवार्य रूप से एक बी-ट्री संरचना के लिए एक पंक्ति-दर-पंक्ति अनियंत्रित सम्मिलित होता है । यह लॉकिंग और लॉगिंग ऑप्टिमाइज़ेशन से लाभ उठाता है, लेकिन बल्क लोड ऑप्टिमाइज़ेशन का समर्थन नहीं करता है ।

नतीजतन, किसी को अक्सर क्वेरी को प्राकृतिक तरीके से विभाजित करके बेहतर प्रदर्शन मिल सकता है: नई पंक्तियों को अस्थायी तालिका या चर में लोड करना, फिर अस्थायी ऑब्जेक्ट से एक अनुकूलित सम्मिलित (स्पष्ट हेलोवीन संरक्षण के बिना) प्रदर्शन करना।

इस पृथक्करण को बनाने से आपको मूल कथन के अलग-अलग हिस्सों को पढ़ने और लिखने की अतिरिक्त स्वतंत्रता मिलती है।

एक साइड नोट के रूप में, यह सोचना दिलचस्प है कि पंक्ति संस्करणों का उपयोग करके हैलोवीन समस्या को कैसे संबोधित किया जा सकता है। शायद SQL सर्वर का भावी संस्करण उपयुक्त परिस्थितियों में वह सुविधा प्रदान करेगा।


जैसा कि माइकल कुटज ने एक टिप्पणी में कहा था, आप स्पष्ट एचपी से बचने के लिए छेद भरने वाले अनुकूलन का फायदा उठाने की संभावना भी तलाश सकते हैं । डेमो के लिए इसे प्राप्त करने का एक तरीका यह है कि आप IDस्तंभ पर एक अनोखा इंडेक्स (यदि आप चाहें तो क्लस्टर किया हुआ) बनाएं A_HEAP_OF_MOSTLY_NEW_ROWS

CREATE UNIQUE INDEX i ON dbo.A_HEAP_OF_MOSTLY_NEW_ROWS (ID);

उस गारंटी के साथ ऑप्टिमाइज़र होल-फिलिंग और रोसेट शेयरिंग का उपयोग कर सकता है:

MERGE dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (SERIALIZABLE) AS HICETY
USING dbo.A_HEAP_OF_MOSTLY_NEW_ROWS AS AHOMNR
    ON AHOMNR.ID = HICETY.ID
WHEN NOT MATCHED BY TARGET
THEN INSERT (ID) VALUES (AHOMNR.ID);

MERGE योजना

दिलचस्प होने के बावजूद, आप ध्यान से कार्यान्वित मैनुअल हैलोवीन प्रोटेक्शन को नियोजित करके कई मामलों में बेहतर प्रदर्शन हासिल कर पाएंगे।


5

पॉल के उत्तर पर थोड़ा विस्तार करने के लिए, स्पूल और टेम्प टेबल तालिका के बीच बीता समय में अंतर का एक हिस्सा DML Request Sortस्पूल प्लान में विकल्प के लिए समर्थन की कमी के लिए नीचे आता है । अनिर्दिष्ट ट्रेस ध्वज 8795 के साथ, अस्थायी तालिका दृष्टिकोण के लिए बीता हुआ समय 4400 एमएस से 5600 एमएस तक कूदता है।

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT new_rows.ID
FROM #CONSULTANT_RECOMMENDED_TEMP_TABLE new_rows
OPTION (MAXDOP 1, QUERYTRACEON 8795);

ध्यान दें कि यह स्पूल प्लान द्वारा किए गए इंसर्ट के बराबर नहीं है। यह क्वेरी लेन-देन लॉग में काफी अधिक डेटा लिखती है।

उसी प्रभाव को कुछ प्रवंचनाओं के साथ उलटा देखा जा सकता है। हैलोवीन प्रोटेक्शन के लिए स्पूल के बजाय एसक्यूएल सर्वर का उपयोग करने के लिए प्रोत्साहित करना संभव है। एक कार्यान्वयन:

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT TOP (987654321) 
maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
    SELECT 1
    FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
    WHERE maybe_new_rows.ID = halloween.ID
)
ORDER BY maybe_new_rows.ID, maybe_new_rows.ID + 1
OPTION (MAXDOP 1, QUERYTRACEON 7470, MERGE JOIN);

अब इस योजना में स्पूल के स्थान पर TOP N Sort ऑपरेटर है। सॉर्ट एक अवरुद्ध ऑपरेटर है इसलिए स्पूल अब आवश्यक नहीं है:

यहाँ छवि विवरण दर्ज करें

इससे भी महत्वपूर्ण बात, अब हमारे पास DML Request Sortविकल्प के लिए समर्थन है । वास्तविक समय के आंकड़ों को फिर से देखते हुए, सम्मिलित ऑपरेटर अब केवल 1623 एमएस लेता है। पूरी योजना वास्तविक योजना का अनुरोध किए बिना निष्पादित करने के लिए लगभग 5400 एमएस लेती है।

जैसा कि ह्यूगो बताते हैं , एगर स्पूल ऑपरेटर ऑर्डर को संरक्षित करता है। यह सबसे आसानी से एक TOP PERCENTयोजना के साथ देखा जा सकता है । यह दुर्भाग्यपूर्ण है कि स्पूल के साथ मूल क्वेरी स्पूल में डेटा की क्रमबद्ध प्रकृति का बेहतर लाभ नहीं उठा सकती है।

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