SQL सर्वर क्वेरी ऑप्टिमाइज़र बार-बार परिकलित मान को एक एकल कंप्यूट स्केलर ऑपरेटर में संयोजित कर सकता है। यह करेगा या नहीं, यह क्वेरी योजना लागत और गणना मूल्य के गुणों पर निर्भर करता है। जैसा कि अपेक्षित था, यह गणना किए गए मूल्यों के लिए ऐसा नहीं करेगा जो कि nondeterministic हैं, जो कुछ अपवाद हैं जैसे कि RAND()। यह भी उपयोगकर्ता परिभाषित कार्यों के लिए ऐसा नहीं करेगा।
मैं एक उपयोगकर्ता परिभाषित फ़ंक्शन उदाहरण के साथ शुरू करूंगा। यहाँ उपयोगकर्ता परिभाषित फ़ंक्शन का एक उत्कृष्ट उदाहरण है:
CREATE OR ALTER FUNCTION dbo.NULL_FUNCTION (@N BIGINT) RETURNS BIGINT
WITH SCHEMABINDING
AS
BEGIN
RETURN NULL;
END;
मैं एक तालिका भी बनाना चाहता हूं और इसमें 100 पंक्तियां डालना चाहता हूं:
CREATE TABLE X_100 (N BIGINT NOT NULL);
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS n FROM L5)
INSERT INTO X_100 WITH (TABLOCK)
SELECT n
FROM Nums WHERE n <= 100;
dbo.NULL_FUNCTIONसमारोह determistic है। निम्नलिखित क्वेरी के लिए इसे कितनी बार निष्पादित किया जाएगा?
SELECT n, dbo.NULL_FUNCTION(n)
FROM X_100;
क्वेरी योजना के आधार पर इसे प्रत्येक पंक्ति में एक बार या 100 बार निष्पादित किया जाएगा:

SQL सर्वर 2016 ने sysinos_exec_function_stats DMV पेश किया । हम उस DMV का स्नैपशॉट ले सकते हैं कि एक क्वेरी द्वारा कितनी बार UDF निष्पादित किया जाता है।
SELECT execution_count
FROM sys.dm_exec_function_stats
WHERE object_id = OBJECT_ID('NULL_FUNCTION');
उस का परिणाम 100 है, इसलिए फ़ंक्शन को 100 बार निष्पादित किया गया था।
आइए एक और सरल प्रश्न का प्रयास करें:
SELECT n, dbo.NULL_FUNCTION(n), dbo.NULL_FUNCTION(n)
FROM X_100;
क्वेरी योजना बताती है कि फ़ंक्शन को 200 बार निष्पादित किया जाएगा:

यह sys.dm_exec_function_statsसुझाव दिया गया कि फ़ंक्शन को 200 बार निष्पादित किया गया था।
ध्यान दें कि आप हमेशा क्वेरी योजना का उपयोग यह पता लगाने के लिए नहीं कर सकते हैं कि एक गणना स्केलर कितनी बार निष्पादित होता है। निम्नलिखित उद्धरण " गणना स्केलर, अभिव्यक्ति और निष्पादन योजना प्रदर्शन " से है:
यह लोगों को यह सोचने की ओर ले जाता है कि कम्प्यूट स्केलर अन्य ऑपरेटरों के बहुमत की तरह व्यवहार करता है: जैसा कि पंक्तियाँ इसके माध्यम से प्रवाहित होती हैं, कम्प्यूट स्केलर में जो भी संगणनाएँ होती हैं उनके परिणाम धारा में जुड़ जाते हैं। यह आम तौर पर सच नहीं है। नाम के बावजूद, गणना स्केलर हमेशा कुछ भी गणना नहीं करता है, और हमेशा एक स्केलर मान नहीं होता है (यह एक वेक्टर, एक उपनाम, या यहां तक कि एक बूलियन विधेय हो सकता है, उदाहरण के लिए)। अधिक बार नहीं, एक गणना स्केलर केवल एक अभिव्यक्ति को परिभाषित करता है; वास्तविक गणना को तब तक के लिए स्थगित कर दिया जाता है जब तक कि निष्पादन योजना में कुछ बाद में परिणाम की आवश्यकता होती है।
चलिए एक और उदाहरण पेश करते हैं। निम्नलिखित प्रश्न के लिए मुझे उम्मीद है कि UDF की गणना एक बार की जाएगी:
WITH NULL_FUNCTION_CTE (NULL_VALUE) AS
(
SELECT DISTINCT dbo.NULL_FUNCTION(0)
)
SELECT n , cte.NULL_VALUE
FROM X_100
CROSS JOIN NULL_FUNCTION_CTE cte;
क्वेरी प्लान बताता है कि इसकी गणना एक बार की जाएगी:

हालाँकि, DMV से सच्चाई का पता चलता है। गणना स्केलर को तब तक टाल दिया जाता है जब तक कि इसकी आवश्यकता नहीं होती है, जो कि ज्वाइन ऑपरेटर में है। इसका मूल्यांकन 100 बार किया जाता है।
आपने यह भी पूछा कि आप एक ही अभिव्यक्ति को कई बार पुनर्गणना करने से बचने के लिए ऑप्टिमाइज़र को प्रोत्साहित करने के लिए क्या कर सकते हैं। सबसे अच्छी बात यह है कि आप अपने कोड में स्केलर यूडीएफ का उपयोग करने से बच सकते हैं। इस सवाल के बाहर कई तरह के प्रदर्शन के मुद्दे हैं, जिसमें मेमोरी ग्रांट को शामिल करना, पूरी क्वेरी को चलाने के लिए मजबूर करना MAXDOP 1, खराब कार्डिनिटी का अनुमान, और अतिरिक्त सीपीयू उपयोग के लिए अग्रणी है। यदि आपको एक यूडीएफ का उपयोग करने की आवश्यकता है और उस यूडीएफ का मूल्य एक स्थिर है तो आप इसे क्वेरी के बाहर और स्थानीय चर में डाल सकते हैं।
यूडीएफ के बिना प्रश्नों के लिए, आप उन लेखन अभिव्यक्तियों से बचने की कोशिश कर सकते हैं जो समान परिणाम लौटाते हैं लेकिन ठीक उसी तरह से टाइप नहीं किए जाते हैं। इस अगले उदाहरण के लिए मैं सार्वजनिक रूप से उपलब्ध AdventureworksDW2016CTP3 डेटाबेस का उपयोग कर रहा हूं, लेकिन वास्तव में कोई भी डेटाबेस करेगा। COUNT(*)इस क्वेरी के लिए कितनी बार गणना की जाएगी ?
SELECT OrderDateKey, COUNT(*)
FROM dbo.FactResellerSales
GROUP BY OrderDateKey
ORDER BY COUNT(*) DESC;
इस क्वेरी के लिए हम हैश मैच (कुल) ऑपरेटर को देखकर यह पता लगा सकते हैं।

COUNT(*)के प्रत्येक अद्वितीय मान के एक बार की जाती है OrderDateKey। ORDER BYक्लॉज को शामिल करने से यह दो बार गणना करने का कारण नहीं बनता है। आप यहां निष्पादन योजना देख सकते हैं ।
अब, एक क्वेरी पर विचार करें जो सटीक समान परिणाम लौटाएगी लेकिन एक अलग तरीके से लिखी जाएगी:
SELECT OrderDateKey, SUM(1)
FROM dbo.FactResellerSales
GROUP BY OrderDateKey
ORDER BY COUNT(*) DESC;
क्वेरी ऑप्टिमाइज़र उन्हें संयोजित करने के लिए पर्याप्त स्मार्ट नहीं है, इसलिए अतिरिक्त काम किया जाएगा:
