एक मल्टी-स्टेटमेंट टेबल-वैल्यू फ़ंक्शन एक टेबल चर में अपना परिणाम देता है।
क्या इन परिणामों को कभी भी पुन: उपयोग किया जाता है, या फ़ंक्शन को हमेशा हर बार पूरी तरह से मूल्यांकन किया जाता है जिसे यह कहा जाता है?
एक मल्टी-स्टेटमेंट टेबल-वैल्यू फ़ंक्शन एक टेबल चर में अपना परिणाम देता है।
क्या इन परिणामों को कभी भी पुन: उपयोग किया जाता है, या फ़ंक्शन को हमेशा हर बार पूरी तरह से मूल्यांकन किया जाता है जिसे यह कहा जाता है?
जवाबों:
मल्टी-स्टेटमेंट टेबल-वैल्यू फ़ंक्शन (msTVF) के परिणामों को कभी भी स्टेटमेंट्स (या कनेक्शन) में कैश्ड या फिर से उपयोग नहीं किया जाता है, लेकिन ऐसे कई तरीके हैं जिनसे msTVF रिजल्ट को एक ही स्टेटमेंट के भीतर दोबारा उपयोग किया जा सकता है । उस हद तक, एक msTVF जरूरी नहीं है कि हर बार इसे कहा जाए।
यह (जानबूझकर अक्षम्य) msTVF पूर्ण पंक्ति में टाइमस्टैम्प के साथ पूर्णांक की एक निर्दिष्ट श्रेणी देता है:
IF OBJECT_ID(N'dbo.IntegerRange', 'TF') IS NOT NULL
DROP FUNCTION dbo.IntegerRange;
GO
CREATE FUNCTION dbo.IntegerRange (@From integer, @To integer)
RETURNS @T table
(
n integer PRIMARY KEY,
ts datetime DEFAULT CURRENT_TIMESTAMP
)
WITH SCHEMABINDING
AS
BEGIN
WHILE @From <= @To
BEGIN
INSERT @T (n)
VALUES (@From);
SET @From = @From + 1;
END;
RETURN;
END;
यदि फ़ंक्शन कॉल के सभी पैरामीटर स्थिरांक (या रनटाइम स्थिरांक) हैं, तो निष्पादन योजना एक बार तालिका चर परिणाम को आबाद करेगी। योजना का शेष भाग कई बार तालिका चर तक पहुँच सकता है। तालिका चर की स्थिर प्रकृति को निष्पादन योजना से पहचाना जा सकता है। उदाहरण के लिए:
SELECT
IR.n,
IR.ts
FROM dbo.IntegerRange(1, 5) AS IR
ORDER BY
IR.n;
के समान परिणाम देता है:
निष्पादन योजना है:
अनुक्रम ऑपरेटर पहले टेबल वेल्यूड फंक्शन ऑपरेटर को कॉल करता है, जो टेबल वेरिएबल को पॉप्युलेट करता है (ध्यान दें कि यह ऑपरेटर कोई पंक्तियाँ नहीं लौटाता है)। अगला, अनुक्रम अपना दूसरा इनपुट कहता है, जो तालिका चर की सामग्री (इस मामले में एक क्लस्टर इंडेक्स स्कैन का उपयोग करके) लौटाता है।
योजना के 'स्थिर' तालिका चर परिणाम का उपयोग करने वाले सस्ता एक अनुक्रम के नीचे तालिका मान्य फ़ंक्शन ऑपरेटर है - योजना के शेष होने से पहले तालिका चर को एक बार पूरी तरह से आबादी की आवश्यकता होती है।
तालिका चर परिणाम को एक से अधिक बार एक्सेस करने के लिए, हम 1 से 5 तक की पंक्तियों के साथ दूसरी तालिका का उपयोग करेंगे:
IF OBJECT_ID(N'dbo.T', 'U') IS NOT NULL
DROP TABLE dbo.T;
CREATE TABLE dbo.T (i integer NOT NULL);
INSERT dbo.T (i)
VALUES (1), (2), (3), (4), (5);
और एक नई क्वेरी जो इस तालिका को हमारे फ़ंक्शन से जोड़ती है (यह समान रूप से लिखा जा सकता है APPLY
):
SELECT T.i,
IR.n,
IR.ts
FROM dbo.T AS T
JOIN dbo.IntegerRange(1, 5) AS IR
ON IR.n = T.i;
परिणाम है:
निष्पादन योजना:
पहले की तरह, अनुक्रम सारणी चर msTVF परिणाम को पहले पॉप्युलेट करता है। अगला, नेस्टेड लूप्स का उपयोग प्रत्येक पंक्ति में टेबल T
से एमएसटीवीएफ परिणाम से एक पंक्ति में शामिल होने के लिए किया जाता है । चूंकि फ़ंक्शन परिभाषा में टेबल चर पर एक उपयोगी सूचकांक शामिल था, इसलिए एक सूचकांक की तलाश की जा सकती है।
प्रमुख बिंदु यह है कि जब msTVF के पैरामीटर स्थिरांक (वैरिएबल और पैरामीटर सहित) या निष्पादन इंजन द्वारा कथन के लिए रनटाइम स्थिरांक के रूप में माना जाता है, तो योजना में msTVF तालिका चर परिणाम के लिए दो अलग-अलग ऑपरेटरों की सुविधा होगी: एक को आबाद करने के लिए तालिका; परिणामों को एक्सेस करने के लिए दूसरा, संभवतः तालिका को कई बार एक्सेस करना, और संभवतः फ़ंक्शन परिभाषा में घोषित अनुक्रमित का उपयोग करना।
जब परस्पर संबंधित पैरामीटर (बाहरी संदर्भ) या गैर-स्थिर फ़ंक्शन मापदंडों का उपयोग किया जाता है, तो अंतर को उजागर करने के लिए, हम तालिका की सामग्री को बदल देंगे T
ताकि फ़ंक्शन को बहुत अधिक काम करना हो:
TRUNCATE TABLE dbo.T;
INSERT dbo.T (i)
VALUES (50001), (50002), (50003), (50004), (50005);
निम्न संशोधित क्वेरी अब T
फ़ंक्शन मापदंडों में से एक में तालिका के लिए एक बाहरी संदर्भ का उपयोग करती है :
SELECT T.i,
IR.n,
IR.ts
FROM dbo.T AS T
CROSS APPLY dbo.IntegerRange(1, T.i) AS IR
WHERE IR.n = T.i;
इस क्वेरी को परिणाम वापस करने में लगभग 8 सेकंड लगते हैं जैसे:
कॉलम में पंक्तियों के बीच के समय के अंतर पर ध्यान दें ts
। WHERE
खंड एक समझदारी से आकार उत्पादन के लिए अंतिम परिणाम को सीमित करता है, लेकिन अक्षम समारोह अभी भी 50,000 के करीब पंक्तियाँ (की सहसंबद्ध मूल्य के आधार पर के साथ तालिका वैरिएबल पॉप्युलेट करने के लिए कुछ समय लगता है i
मेज से T
)।
निष्पादन योजना है:
एक अनुक्रम ऑपरेटर की कमी पर ध्यान दें। अब, एक एकल टेबल वेल्यूएड फंक्शन ऑपरेटर है जो टेबल वेरिएबल को पॉप्युलेट करता है और नेस्टेड लूप्स के प्रत्येक पुनरावृत्ति पर अपनी पंक्तियों को वापस करता है ।
स्पष्ट होने के लिए: तालिका T में सिर्फ 5 पंक्तियों के साथ, तालिका मान्यता प्राप्त फ़ंक्शन ऑपरेटर 5 बार चलता है। यह पहली यात्रा पर 50,001 पंक्तियों को उत्पन्न करता है, दूसरे पर 50,002 ... और इसी तरह। तालिका चर को पुनरावृत्तियों के बीच 'दूर फेंक दिया' (काट दिया गया) है, इसलिए प्रत्येक पाँच कॉल पूर्ण जनसंख्या है। यही कारण है कि यह इतना धीमा है, और प्रत्येक पंक्ति को परिणाम में दिखाई देने के लिए समान समय लगता है।
साइड नोट्स:
स्वाभाविक रूप से, ऊपर का परिदृश्य यह दिखाने के लिए जानबूझकर वंचित है कि प्रदर्शन कितना खराब हो सकता है जब एमएसटीवीएफ प्रत्येक पुनरावृत्ति पर कई पंक्तियों को पॉप्युलेट करता है।
उपरोक्त कोड का एक समझदार कार्यान्वयन दोनों msTVF मापदंडों को निर्धारित करेगा i
और निरर्थक WHERE
खंड को हटा देगा । टेबल वेरिएबल को अभी भी प्रत्येक पुनरावृत्ति पर छोटा और पुन: आकार दिया जाएगा, लेकिन हर बार केवल एक पंक्ति के साथ।
हम न्यूनतम चरणों में अधिकतम और अधिकतम i
मूल्य प्राप्त कर सकते हैं T
और उन्हें एक पूर्व चरण में चर में संग्रहीत कर सकते हैं। सहसंबद्ध मापदंडों के बजाय चर के साथ फ़ंक्शन को कॉल करने से 'स्थिर' तालिका चर पैटर्न का उपयोग किया जा सकेगा।
मूल प्रश्न को एक बार फिर से लौटाना, जहां अनुक्रम स्थिर पैटर्न का उपयोग नहीं किया जा सकता है, SQL सर्वर ट्रेंकुलेटिंग और पुन: उपयोग करने से बच सकता है अगर कोई नेस्टर्ड लूप के पूर्व चलना के बाद से कोई भी सहसंबंधित पैरामीटर नहीं बदला है।
इसे प्रदर्शित करने के लिए, हम T
पाँच समान i
मूल्यों वाली सामग्रियों को प्रतिस्थापित करेंगे :
TRUNCATE TABLE dbo.T;
INSERT dbo.T (i)
VALUES (50005), (50005), (50005), (50005), (50005);
एक सहसंबद्ध पैरामीटर के साथ क्वेरी फिर से:
SELECT T.i,
IR.n,
IR.ts
FROM dbo.T AS T
CROSS APPLY dbo.IntegerRange(1, T.i) AS IR
WHERE IR.n = T.i;
इस बार परिणाम लगभग 1.5 सेकंड में दिखाई देते हैं :
प्रत्येक पंक्ति पर समान टाइमस्टैम्प पर ध्यान दें। तालिका चर में कैश्ड परिणाम का पुन: उपयोग इसके पुनरावृत्तियों के लिए किया जाता है जहाँ सहसंबंधित मूल्य i
अपरिवर्तित होता है। हर बार 50,005 पंक्तियों को सम्मिलित करने की तुलना में परिणाम का पुन: उपयोग बहुत तेजी से होता है।
निष्पादन योजना पहले की तरह ही दिखती है:
मुख्य अंतर तालिका मान्य फ़ंक्शन ऑपरेटर के वास्तविक रिबाइंड और वास्तविक रिवाइंड गुणों में है:
जब सहसंबद्ध पैरामीटर नहीं बदलते हैं, तो SQL सर्वर तालिका चर में वर्तमान परिणामों को फिर से खोल (रिवाइंड) कर सकता है। जब सहसंबंध बदल जाता है, तो SQL सर्वर को टेबल चर (रिबंड) को छोटा करना और फिर से बनाना होगा। एक विद्रोह पहली यात्रा पर होता है; चार बाद के पुनरावृत्तियों सभी के बाद से रिवाइंड हैं क्योंकि मूल्य T.i
अपरिवर्तित है।