निम्न तालिका पर विचार करें जो किसी स्रोत तालिका से पंक्तियाँ सम्मिलित करती हैं यदि वे लक्ष्य तालिका में पहले से नहीं हैं:
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;