मैं परीक्षण को
. के रूप में फिर से लिखूंगाIF CASE
WHEN EXISTS (SELECT ...) THEN CASE
WHEN EXISTS (SELECT ...) THEN 1
END
END = 1
जैसा कि यहां बताया गया है, यह शॉर्ट सर्किटिंग की गारंटी देता है, लेकिन इसका मतलब यह है कि आपको इसे ऑप्टिमाइज़र पर छोड़ने के बजाय सामने वाले का मूल्यांकन करने के लिए सबसे सस्ता चुनना होगा।
नीचे दिए गए मेरे अत्यंत सीमित परीक्षणों में परीक्षण करते समय निम्नलिखित सही प्रतीत हुए
<एच3>1.EXISTS AND EXISTS
EXISTS AND EXISTS
संस्करण सबसे अधिक समस्याग्रस्त लगता है। यह जंजीर एक साथ कुछ बाहरी अर्ध जुड़ती है। किसी भी मामले में यह परीक्षण के क्रम को फिर से व्यवस्थित करने की कोशिश नहीं करता है और सस्ता पहले करता है (इस ब्लॉग पोस्ट के दूसरे भाग में चर्चा की गई एक समस्या)। IF ...
. में अगर इसमें शॉर्ट सर्किट नहीं होता तो इससे कोई फर्क नहीं पड़ता। हालाँकि जब इस संयुक्त विधेय को WHERE
. में रखा जाता है खंड योजना में परिवर्तन होता है और यह करता है शॉर्ट सर्किट ताकि पुनर्व्यवस्था फायदेमंद हो सके।
/*All tests are testing "If False And False"*/
IF EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
AND EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
PRINT 'Y'
/*
Table 'spt_values'. Scan count 1, logical reads 9
Table 'spt_monitor'. Scan count 1, logical reads 1
*/
IF EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
AND EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
PRINT 'Y'
/*
Table 'spt_monitor'. Scan count 1, logical reads 1
Table 'spt_values'. Scan count 1, logical reads 9
*/
SELECT 1
WHERE EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
AND EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/
SELECT 1
WHERE EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)
AND EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_values'. Scan count 1, logical reads 9
*/
इन सभी के लिए योजनाएँ बहुत समान दिखाई देती हैं। SELECT 1 WHERE ...
. के बीच व्यवहार में अंतर का कारण संस्करण और IF ...
संस्करण यह है कि पूर्व के लिए यदि स्थिति गलत है तो सही व्यवहार कोई परिणाम नहीं लौटाना है, इसलिए यह केवल OUTER SEMI JOINS
को जंजीर देता है और यदि कोई गलत है तो शून्य पंक्तियाँ अगली पंक्ति तक ले जाती हैं।
हालांकि IF
संस्करण हमेशा 1 या शून्य का परिणाम वापस करने की आवश्यकता है। यह योजना अपने बाहरी जोड़ में एक जांच कॉलम का उपयोग करती है और इसे गलत पर सेट करती है यदि EXISTS
परीक्षण पारित नहीं किया गया है (केवल पंक्ति को त्यागने के बजाय)। इसका मतलब है कि अगले जॉइन में हमेशा 1 पंक्ति फीडिंग होती है और इसे हमेशा निष्पादित किया जाता है।
CASE
संस्करण की एक समान योजना है लेकिन यह एक PASSTHRU
. का उपयोग करता है भविष्यवाणी करें कि यह जॉइन के निष्पादन को छोड़ने के लिए उपयोग करता है यदि पिछला THEN
शर्त पूरी नहीं हुई। मुझे यकीन नहीं है कि क्यों संयुक्त AND
s समान दृष्टिकोण का उपयोग नहीं करेंगे।
EXISTS OR EXISTS
EXISTS OR EXISTS
संस्करण में एक संयोजन का उपयोग किया गया था (UNION ALL
) ऑपरेटर बाहरी सेमी जॉइन के आंतरिक इनपुट के रूप में। इस व्यवस्था का मतलब है कि जैसे ही पहला लौटाया जाता है, यह आंतरिक पक्ष से पंक्तियों का अनुरोध करना बंद कर सकता है (यानी यह प्रभावी रूप से शॉर्ट सर्किट कर सकता है) सभी 4 प्रश्न उसी योजना के साथ समाप्त हो गए जहां सस्ता विधेय का मूल्यांकन पहले किया गया था।
/*All tests are testing "If True Or True"*/
IF EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=1)
OR EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
PRINT 'Y'
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/
IF EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
OR EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)= 1)
PRINT 'Y'
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/
SELECT 1
WHERE EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)= 1)
OR EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/
SELECT 1
WHERE EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)<>1)
OR EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=1)
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/
<एच3>3. एक ELSE
जोड़ना
मेरे साथ ऐसा हुआ कि मैं AND
. को परिवर्तित करने के लिए डी मॉर्गन के नियम का प्रयास कर रहा था करने के लिए OR
और देखें कि क्या इससे कोई फर्क पड़ता है। पहली क्वेरी को परिवर्तित करने से देता है
IF NOT ((NOT EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
OR NOT EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1)))
PRINT 'Y'
ELSE
PRINT 'N'
/*
Table 'spt_monitor'. Scan count 1, logical reads 1
Table 'spt_values'. Scan count 1, logical reads 9
*/
तो यह अभी भी शॉर्ट सर्किटिंग व्यवहार पर कोई फर्क नहीं पड़ता है। हालांकि अगर आप NOT
. को हटाते हैं और IF ... ELSE
. के क्रम को उलट दें शर्तें यह अब करता है शॉर्ट सर्किट!
IF (NOT EXISTS(SELECT COUNT(*) FROM master..spt_monitor HAVING COUNT(*)=2)
OR NOT EXISTS (SELECT COUNT(*) FROM master..spt_values HAVING COUNT(*)=1))
PRINT 'N'
ELSE
PRINT 'Y'
/*
Table 'Worktable'. Scan count 0, logical reads 0
Table 'spt_monitor'. Scan count 1, logical reads 1
*/