टेम्‍प चर को इंडेक्‍स स्‍कैन करने के लिए क्‍यों मजबूर किया जाता है जबकि टेम्‍प टेबल का उपयोग तलाश और बुकमार्क लुकअप के लिए होता है


18

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

तालिका पॉप्युलेट करना:

CREATE TABLE dbo.Test 
(
    RowKey INT NOT NULL PRIMARY KEY, 
    SecondColumn CHAR(1) NOT NULL DEFAULT 'x',
    ForeignKey INT NOT NULL 
) 

INSERT dbo.Test 
(
    RowKey, 
    ForeignKey
) 
SELECT TOP 1000000 
    ROW_NUMBER() OVER (ORDER BY (SELECT 0)),
    ABS(CHECKSUM(NEWID()) % 10)     
FROM sys.all_objects s1
CROSS JOIN sys.all_objects s2 

CREATE INDEX ix_Test_1 ON dbo.Test (ForeignKey) 

किसी एकल रिकॉर्ड के साथ तालिका चर को पॉप्युलेट करें और विदेशी कुंजी कॉलम पर खोज करके प्राथमिक कुंजी और दूसरे कॉलम को देखने का प्रयास करें:

DECLARE @Keys TABLE (RowKey INT NOT NULL) 

INSERT @Keys (RowKey) VALUES (10)

SELECT 
    t.RowKey,
    t.SecondColumn
FROM
    dbo.Test t 
INNER JOIN 
    @Keys k
ON
    t.ForeignKey = k.RowKey

नीचे निष्पादन योजना है:

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

अब इसके बजाय एक अस्थायी तालिका का उपयोग करके एक ही क्वेरी:

CREATE TABLE #Keys (RowKey INT NOT NULL) 

INSERT #Keys (RowKey) VALUES (10) 

SELECT 
    t.RowKey,
    t.SecondColumn
FROM
    dbo.Test t 
INNER JOIN 
    #Keys k
ON
    t.ForeignKey = k.RowKey

यह क्वेरी प्लान एक सीक और बुकमार्क लुकअप का उपयोग करता है:

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

ऑप्टिमाइज़र क्यों तैयार है कि टेम्प्लेट लुकअप को टेम्प टेबल के साथ किया जाए, लेकिन टेबल वेरिएबल को नहीं?

तालिका चर का उपयोग इस उदाहरण में किया जाता है कि संग्रहीत प्रक्रिया में उपयोगकर्ता द्वारा परिभाषित तालिका प्रकार के माध्यम से आने वाले डेटा का प्रतिनिधित्व किया जाए।

मुझे एहसास है कि विदेशी महत्वपूर्ण मूल्य सैकड़ों बार होने पर सूचकांक की तलाश उचित नहीं हो सकती है। उस मामले में, एक स्कैन शायद एक बेहतर विकल्प होगा। मेरे द्वारा बनाए गए परिदृश्य के लिए, 10. के मान के साथ कोई पंक्ति नहीं थी। मुझे अभी भी लगता है कि व्यवहार दिलचस्प है और जानना चाहेंगे कि क्या इसका कोई कारण है।

एसक्यूएल फिडल

जोड़ने OPTION (RECOMPILE)से व्यवहार नहीं बदला। UDDT के पास एक प्राथमिक कुंजी है।

@@VERSION SQL Server 2008 R2 (SP2) है - 10.50.4042.0 (X64) (7601 बनाएँ: सर्विस पैक 1) (हाइपरवाइज़र)

जवाबों:


15

व्यवहार का कारण यह है कि SQL सर्वर यह निर्धारित नहीं कर सकता है कि फॉरेनकेय से कितनी पंक्तियाँ मेल खाएँगी, क्योंकि रोवे के साथ अग्रणी कॉलम के रूप में कोई इंडेक्स नहीं है (यह #temp टेबल पर आँकड़ों से इसे घटा सकता है, लेकिन वे नहीं करते हैं तालिका चर / UDTTs के लिए मौजूद है), इसलिए यह 100,000 पंक्तियों का अनुमान लगाता है, जो एक तलाश + खोज की तुलना में स्कैन के साथ बेहतर तरीके से नियंत्रित किया जाता है। जब तक SQL सर्वर को पता चलता है कि केवल एक पंक्ति है, तब तक बहुत देर हो चुकी होती है।

आप अपने यूडीटीटी का निर्माण करने में सक्षम हो सकते हैं; SQL सर्वर के अधिक आधुनिक संस्करणों में आप तालिका चर पर द्वितीयक इंडेक्स बना सकते हैं, लेकिन 2008 सिंटैक्स में यह सिंटैक्स उपलब्ध नहीं है।

यदि आप एक नेस्टेड छोरों को जोड़कर बिटमैप / जांच से बचने की कोशिश करते हैं तो बीटीडब्ल्यू आप कम से कम (मेरे सीमित परीक्षणों में) व्यवहार की तलाश कर सकते हैं:

DECLARE @Keys TABLE (RowKey INT PRIMARY KEY); -- can't hurt

INSERT @Keys (RowKey) VALUES (10);

SELECT 
     t.RowKey
    ,t.SecondColumn
FROM
    dbo.Test t 
INNER JOIN 
    @Keys k
ON
    t.ForeignKey = k.RowKey
    OPTION (LOOP JOIN);

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

अधिक जटिल प्रश्नों के लिए, और जब आप SQL Server 2012 या उससे ऊपर जाते हैं, तो संभव है कि ध्वज 2453 का पता लगा सके। हालाँकि इस ध्वज ने इस सरल जुड़ने में मदद नहीं की, हालाँकि और एक ही अस्वीकरण लागू होता है - यह सिर्फ एक वैकल्पिक चीज है जिसे आप आमतौर पर एक टन प्रलेखन और कठोर प्रतिगमन परीक्षण प्रक्रियाओं के बिना नहीं करना चाहिए।

साथ ही, सर्विस पैक 1 लंबे समय से समर्थन से बाहर है, आपको सर्विस पैक 3 + MS15-058 पर मिलना चाहिए ।


3

टेबल चर और अस्थायी टेबल को कई तरीकों से अलग-अलग तरीके से संभाला जाता है। यहाँ बहुत सारी बारीकियों के साथ एक शानदार उत्तर है जहाँ वे अलग हैं।

विशेष रूप से आपके मामले में मुझे लगता है कि यह तथ्य यह है कि अस्थायी तालिकाओं में अतिरिक्त आँकड़े उत्पन्न हो सकते हैं और समानांतर योजनाएं हो सकती हैं, जबकि तालिका चर में अधिक सीमित आँकड़े (कोई स्तंभ स्तर के आँकड़े) नहीं हैं और कोई समानांतर योजनाएँ आपके अपराधी नहीं हैं।

आप संग्रहीत कार्यविधि की अवधि के लिए तालिका चर को एक अस्थायी तालिका में डंप करने से बहुत बेहतर हो सकते हैं।

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