क्या SQL सर्वर हर पंक्ति के लिए एक बार फ़ंक्शन का मूल्यांकन करता है?


9

मेरे पास इस तरह से एक प्रश्न है:

SELECT col1
FROM   MyTable
WHERE  
    DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE())) 
       BETWEEN col2 
       AND     col3
;

यह इस तरह के निष्पादन योजना पर एक टूलटिप देता है:

निष्पादन टूलटिप

क्या dateaddक्वेरी में हर पंक्ति के लिए साधक का भाग निष्पादित होता है? या SQL Server पूरे क्वेरी के लिए एक बार मान की गणना करता है?

जवाबों:


13

कुछ कार्य जिन्हें रनटाइम स्थिरांक के रूप में जाना जाता है वे निरंतर तह नामक प्रक्रिया से गुजरते हैं । By फोल्डिंग ’द्वारा एक स्थिर अभिव्यक्ति को क्वेरी निष्पादन में जल्दी मूल्यांकन किया जाता है, परिणाम को आवश्यकता के बजाय कैश और कैश्ड परिणाम दिया जाता है। आपकी क्वेरी में अभिव्यक्ति DATEADD(dd, 0, DATEDIFF(dd, 0, getdate())), afaik, एक रनटाइम स्थिरांक है और इस प्रकार इसे केवल एक बार प्रति क्वेरी के अनुसार मोड़ा और मूल्यांकन किया जाएगा।

ट्रिविया के रूप में: वह RAND()फ़ंक्शन जो किसी के अनफिट होने की उम्मीद करता है, वास्तव में फोल्डेबल होता है, जिससे कुछ अप्रत्याशित व्यवहार होता है। लेकिन अन्य, उदाहरण के लिए NEWID(), तह नहीं हैं और प्रति पंक्ति एक मूल्यांकन को मजबूर करेंगे।


2
@StuartBlackler - यहां बताया गया है कि SQL सर्वर फोल्ड कैसे कार्य करता है GETDATE()
निक चामास

2

निष्पादन योजनाएं महान हैं लेकिन कभी-कभी वे आपको केवल सच नहीं बताते हैं। तो यहाँ प्रदर्शन परीक्षण के आधार पर एक प्रमाण है।

(और निचला रेखा - हर पंक्ति के लिए अभिव्यक्ति का मूल्यांकन नहीं किया जा रहा है)


;with t(i) as (select 0 union all select i+1 from t where i < 9)
select getdate()-1 as col1,getdate() as col2,getdate() as col3 
into #t 
from t t0,t t1,t t2,t t3,t t4,t t5,t t6,t t7

(100000000 पंक्ति) प्रभावित

यह ओपी क्वेरी है और इसे चलाने में लगभग 12 सेकंड लगते हैं

SELECT col1
FROM   #t
WHERE  
    DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE())) 
       BETWEEN col2 
       AND     col3
;

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

declare @dt datetime = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE())) 

SELECT col1
FROM   #t
WHERE  
      @dt
       BETWEEN col2 
       AND     col3
;

और परिणामों को सत्यापित करने के लिए -
यह क्वेरी जो कॉल 1 पर गणना करती है और इसलिए प्रत्येक पंक्ति के लिए अभिव्यक्ति को पुन: परिकलित करना होता है, जिसे चलाने में लगभग 30 सेकंड लगते हैं।

SELECT col1
FROM   #t
WHERE  
    DATEADD(dd, 0, DATEDIFF(dd, 0, col1)) 
       BETWEEN col2 
       AND     col3
;

एक ही मीट्रिक के बारे में दिखाते हुए सभी प्रश्नों को बार-बार निष्पादित किया गया

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