एसक्यूएल केस? केक का टुकड़ा!
वाक़ई?
तब तक नहीं जब तक आप 3 परेशानी वाली समस्याओं से नहीं टकराते जो रनटाइम त्रुटियों और धीमी प्रदर्शन का कारण बन सकती हैं।
यदि आप यह देखने के लिए उपशीर्षक स्कैन करने का प्रयास कर रहे हैं कि समस्याएँ क्या हैं, तो मैं आपको दोष नहीं दे सकता। मेरे सहित पाठक अधीर हैं।
मुझे विश्वास है कि आप पहले से ही SQL CASE की मूल बातें जानते हैं, इसलिए, मैंने आपको लंबे परिचय से बोर नहीं किया। आइए गहराई से समझें कि हुड के नीचे क्या हो रहा है।
1. SQL केस हमेशा क्रमिक रूप से मूल्यांकन नहीं करता है
Microsoft SQL CASE कथन में व्यंजकों का मूल्यांकन अधिकतर क्रमिक रूप से या बाएँ से दाएँ किया जाता है। हालाँकि, यह एक अलग कहानी है, जब इसे समग्र कार्यों के साथ उपयोग किया जाता है। आइए एक उदाहरण लेते हैं:
-- aggregate function evaluated first and generated an error
DECLARE @value INT = 0;
SELECT CASE WHEN @value = 0 THEN 1 ELSE MAX(1/@value) END;
उपरोक्त कोड सामान्य दिखता है। अगर मैं आपसे पूछूं कि उन बयानों का परिणाम क्या है, तो आप शायद कहेंगे 1. दृश्य निरीक्षण हमें बताता है कि क्योंकि @value 0 पर सेट है। जब @value 0 है, तो परिणाम 1 है।
लेकिन यहां ऐसा नहीं है। SQL सर्वर प्रबंधन स्टूडियो के वास्तविक परिणाम पर एक नज़र डालें:
Msg 8134, Level 16, State 1, Line 4
Divide by zero error encountered.
लेकिन क्यों?
जब सशर्त अभिव्यक्तियाँ SQL CASE में MAX () जैसे कुल कार्यों का उपयोग करती हैं, तो इसका मूल्यांकन पहले किया जाता है। इस प्रकार, MAX(1/@value) शून्य त्रुटि से विभाजन का कारण बनेगा क्योंकि @value शून्य है।
छुपाने पर यह स्थिति और भी ज्यादा तकलीफदेह होती है। मैं इसे बाद में समझाऊंगा।
2. साधारण SQL केस एक्सप्रेशन कई बार मूल्यांकन करता है
तो क्या?
अच्छा प्रश्न। सच तो यह है कि यदि आप शाब्दिक या सरल भावों का उपयोग करते हैं तो कोई समस्या नहीं है। लेकिन अगर आप सबक्वेरी को सशर्त अभिव्यक्ति के रूप में उपयोग करते हैं, तो आपको एक बड़ा आश्चर्य होगा।
नीचे दिए गए उदाहरण को आजमाने से पहले, आप यहां से डेटाबेस की एक प्रति को पुनर्स्थापित करना चाह सकते हैं। हम इसे बाकी उदाहरणों के लिए इस्तेमाल करेंगे।
अब, इस बहुत ही सरल प्रश्न पर विचार करें:
SELECT TOP 1 manufacturerID FROM SportsCars
यह बहुत आसान है, है ना? यह डेटा के 1 कॉलम के साथ 1 पंक्ति देता है। सांख्यिकी IO न्यूनतम तार्किक पठन को प्रकट करता है।
त्वरित नोट :अशिक्षित के लिए, उच्च तार्किक पठन होने से क्वेरी धीमी हो जाती है। अधिक जानकारी के लिए इसे पढ़ें।
निष्पादन योजना भी एक सरल प्रक्रिया का खुलासा करती है:
अब, उस क्वेरी को एक सबक्वेरी के रूप में CASE एक्सप्रेशन में डालते हैं:
-- Using a subquery in a SQL CASE
DECLARE @manufacturer NVARCHAR(50)
SET @manufacturer = (CASE (SELECT TOP 1 manufacturerID FROM SportsCars)
WHEN 6 THEN 'Alfa Romeo'
WHEN 21 THEN 'Aston Martin'
WHEN 64 THEN 'Ferrari'
WHEN 108 THEN 'McLaren'
ELSE 'Others'
END)
SELECT @manufacturer;
विश्लेषण
अपनी उंगलियों को क्रॉस करें क्योंकि यह तार्किक रीड को 4 गुना अधिक उड़ा देगा।
हैरत में डालना! केवल 2 तार्किक पठन के साथ चित्र 1 की तुलना में, यह 4 गुना अधिक है। इस प्रकार, क्वेरी 4 गुना धीमी है। ऐसा कैसे हो सकता है? हमने केवल एक बार सबक्वेरी देखी।
लेकिन यह कहानी का अंत नहीं है। निष्पादन योजना देखें:
हम चित्र 4 में शीर्ष और सूचकांक स्कैन ऑपरेटरों के 4 उदाहरण देखते हैं। यदि प्रत्येक शीर्ष और सूचकांक स्कैन 2 तार्किक रीड का उपभोग करता है, तो यह बताता है कि तार्किक रीड्स चित्र 3 में 8 क्यों हो गए। और चूंकि प्रत्येक टॉप और इंडेक्स स्कैन की लागत 25% है। , यह हमें यह भी बताता है कि वे वही हैं।
लेकिन यह वहां खत्म नहीं होता है। कंप्यूट स्केलर ऑपरेटर के गुण बताते हैं कि पूरे स्टेटमेंट को कैसे व्यवहार किया जाता है।
हम 4 केस देखते हैं जब कंप्यूट स्केलर ऑपरेटर डिफाइंड वैल्यू से एक्सप्रेशन आते हैं। ऐसा लगता है कि हमारी साधारण CASE अभिव्यक्ति इस तरह खोजी गई CASE अभिव्यक्ति बन गई:
DECLARE @manufacturer NVARCHAR(50)
SET @manufacturer = (CASE
WHEN (SELECT TOP 1 manufacturerID FROM SportsCars) = 6 THEN 'Alfa Romeo'
WHEN (SELECT TOP 1 manufacturerID FROM SportsCars) = 21 THEN 'Aston Martin'
WHEN (SELECT TOP 1 manufacturerID FROM SportsCars) = 64 THEN 'Ferrari'
WHEN (SELECT TOP 1 manufacturerID FROM SportsCars) = 108 THEN 'McLaren'
ELSE 'Others'
END)
SELECT @manufacturer;
आओ पूर्वावलोकन कर लें। प्रत्येक टॉप और इंडेक्स स्कैन ऑपरेटर के लिए 2 लॉजिकल रीड थे। इसे 4 से गुणा करने पर 8 लॉजिकल रीड बनते हैं। हमने कंप्यूट स्केलर ऑपरेटर में 4 केस व्हेन एक्सप्रेशन भी देखे।
अंत में, साधारण CASE एक्सप्रेशन में सबक्वेरी का मूल्यांकन 4 बार किया गया। यह आपकी क्वेरी से पिछड़ जाएगा।
साधारण केस एक्सप्रेशन में सबक्वेरी के एकाधिक मूल्यांकन से कैसे बचें
SQL में कई केस स्टेटमेंट जैसी प्रदर्शन समस्या से बचने के लिए, हमें क्वेरी को फिर से लिखना होगा।
सबसे पहले, सबक्वेरी के परिणाम को एक वेरिएबल में रखें। फिर, सरल SQL सर्वर CASE अभिव्यक्ति की स्थिति में उस चर का उपयोग इस तरह करें:
DECLARE @manufacturer NVARCHAR(50)
DECLARE @ManufacturerID INT -- create a new variable
-- store the result of the subquery in a variable
SET @ManufacturerID = (SELECT TOP 1 manufacturerID FROM SportsCars)
-- use the new variable in the simple CASE expression
SET @manufacturer = (CASE @ManufacturerID
WHEN 6 THEN 'Alfa Romeo'
WHEN 21 THEN 'Aston Martin'
WHEN 64 THEN 'Ferrari'
WHEN 108 THEN 'McLaren'
ELSE 'Others'
END)
SELECT @manufacturer;
क्या यह एक अच्छा फिक्स है? आइए देखें सांख्यिकी IO में तार्किक पठन:
हम संशोधित क्वेरी से कम तार्किक पठन देखते हैं। सबक्वायरी को बाहर निकालना और परिणाम को एक चर में असाइन करना बहुत बेहतर है। निष्पादन योजना के बारे में कैसे? इसे नीचे देखें।
टॉप और इंडेक्स स्कैन ऑपरेटर केवल एक बार दिखाई दिया, 4 बार नहीं। बढ़िया!
टेकअवे :CASE एक्सप्रेशन में एक शर्त के रूप में सबक्वेरी का उपयोग न करें। यदि आपको कोई मान पुनर्प्राप्त करने की आवश्यकता है, तो सबक्वायरी के परिणाम को पहले एक चर में रखें। फिर, उस चर का उपयोग CASE व्यंजक में करें।
3. ये 3 बिल्ट-इन फंक्शंस गुप्त रूप से SQL केस में बदल जाते हैं
एक रहस्य है, और SQL सर्वर CASE कथन का इससे कुछ लेना-देना है। यदि आप नहीं जानते कि ये 3 कार्य कैसे व्यवहार करते हैं, तो आपको नहीं पता होगा कि आप एक गलती कर रहे हैं जिसे हमने पहले अंक # 1 और # 2 से बचने की कोशिश की थी। ये रहे:
- आईआईएफ
- COALESCE
- चुनें
आइए एक-एक करके उनकी जांच करें।
आईआईएफ
मैंने अनुप्रयोगों के लिए विजुअल बेसिक और विजुअल बेसिक में तत्काल आईएफ, या आईआईएफ का उपयोग किया। यह सी # के टर्नरी ऑपरेटर के बराबर भी है:<स्थिति>?
एक शर्त दी गई यह फ़ंक्शन शर्त परिणाम के आधार पर 2 तर्कों में से 1 लौटाएगा। और यह फंक्शन टी-एसक्यूएल में भी उपलब्ध है। WHERE क्लॉज में CASE स्टेटमेंट को SELECT स्टेटमेंट में इस्तेमाल किया जा सकता है
लेकिन यह एक लंबी CASE अभिव्यक्ति का सिर्फ एक गन्ना है। हम कैसे जानते हैं? आइए एक उदाहरण की जांच करें।
SELECT IIF((SELECT Model FROM SportsCars WHERE SportsCarID = 1276) = 'McLaren Senna', 'Yes', 'No');
इस क्वेरी का परिणाम 'नहीं' है। हालांकि, कंप्यूट स्केलर के गुणों के साथ निष्पादन योजना देखें।
चूंकि आईआईएफ केस है, तो आपको क्या लगता है कि अगर आप ऐसा कुछ निष्पादित करते हैं तो क्या होगा?
DECLARE @averageCost MONEY = 1000000.00;
DECLARE @noOfPayments TINYINT = 0; -- intentional to force the error
SELECT IIF((SELECT Model FROM SportsCars WHERE SportsCarID = 1276) = 'SF90 Spider', 83333.33,MIN(@averageCost / @noOfPayments));
यदि @noOfPayments 0 है, तो इसका परिणाम शून्य से विभाजित त्रुटि में होगा। पहले बिंदु #1 पर भी ऐसा ही हुआ था।
आपको आश्चर्य हो सकता है कि इस त्रुटि का कारण क्या है क्योंकि उपरोक्त क्वेरी का परिणाम TRUE होगा और इसे 83333.33 वापस करना चाहिए। बिंदु #1 फिर से जांचें।
इस प्रकार, यदि आप IIF का उपयोग करते समय इस तरह की त्रुटि से फंस गए हैं, तो SQL CASE अपराधी है।
COALESCE
COALESCE भी SQL CASE व्यंजक का एक शॉर्टकट है। यह मानों की सूची का मूल्यांकन करता है और पहला गैर-शून्य मान देता है। COALESCE के बारे में पिछले लेख में, मैंने एक उदाहरण प्रस्तुत किया जो एक सबक्वेरी का दो बार मूल्यांकन करता है। लेकिन मैंने निष्पादन योजना में SQL केस को प्रकट करने के लिए एक और विधि का उपयोग किया। यहां एक और उदाहरण दिया गया है जो समान तकनीकों का उपयोग करेगा।
SELECT
COALESCE(m.Manufacturer + ' ','') + sc.Model AS Car
FROM SportsCars sc
LEFT JOIN Manufacturers m ON sc.ManufacturerID = m.ManufacturerID
आइए निष्पादन योजना और कंप्यूट स्केलर परिभाषित मान देखें।
एसक्यूएल केस ठीक है। COALESCE कीवर्ड परिभाषित मान विंडो में कहीं नहीं है। यह इस समारोह के पीछे के रहस्य को साबित करता है।
लेकिन वह सब नहीं है। आपने कितनी बार [वाहन] देखा।[dbo].[Styles].[Style] परिभाषित मान विंडो में? दो बार! यह आधिकारिक Microsoft दस्तावेज़ीकरण के अनुरूप है। कल्पना कीजिए कि COALESCE में तर्कों में से कोई एक उपश्रेणी है। फिर, तार्किक पठन को दोगुना करें और धीमी गति से निष्पादन भी प्राप्त करें।
चुनें
अंत में, चुनें। यह MS Access CHOOSE फंक्शन के समान है। यह सूचकांक स्थिति के आधार पर मूल्यों की सूची से 1 मान देता है। यह एक सरणी में अनुक्रमणिका के रूप में भी कार्य करता है।
आइए देखें कि क्या हम एक उदाहरण के साथ SQL CASE में परिवर्तन को खोद सकते हैं। नीचे दिए गए कोड को देखें:
;WITH McLarenCars AS
(
SELECT
CASE
WHEN sc.Model IN ('Artura','Speedtail','P1/ P1 GTR','P1 LM') THEN '1'
ELSE '2'
END AS [type]
,sc.Model
,s.Style
FROM SportsCars sc
INNER JOIN Styles s ON sc.StyleID = s.StyleID
WHERE sc.ManufacturerID = 108
)
SELECT
Model
,Style
,CHOOSE([Type],'Hybrid','Gasoline') AS [type]
FROM McLarenCars
हमारा CHOOSE उदाहरण है। अब, निष्पादन योजना और कंप्यूट स्केलर परिभाषित मूल्यों की जाँच करें:
क्या आप चित्र 10 में परिभाषित मान विंडो में CHOOSE कीवर्ड देखते हैं? केस के बारे में कब?
पिछले उदाहरणों की तरह, यह CHOOSE फ़ंक्शन लंबी CASE अभिव्यक्ति के लिए सिर्फ एक गन्ना है। और चूंकि क्वेरी में CHOOSE के लिए 2 आइटम हैं, CASE जब कीवर्ड दो बार दिखाई दिए। लाल बॉक्स में संलग्न परिभाषित मान विंडो देखें।
हालाँकि, हमारे यहाँ SQL में कई मामले हैं। यह CTE की आंतरिक क्वेरी में CASE अभिव्यक्ति के कारण है। यदि आप ध्यान से देखें, तो आंतरिक क्वेरी का वह भाग भी दो बार प्रकट होता है।
टेकअवे
अब जब रहस्य खुल गए हैं, तो हमने क्या सीखा?
- एसक्यूएल केस जब समग्र कार्यों का उपयोग किया जाता है तो अलग तरह से व्यवहार करता है। MIN, MAX, या COUNT जैसे समेकित कार्यों के लिए तर्क देते समय सावधान रहें।
- एक साधारण CASE व्यंजक का कई बार मूल्यांकन किया जाएगा। इसे नोटिस करें और सबक्वायरी पास करने से बचें। हालांकि यह वाक्यात्मक रूप से सही है, लेकिन यह खराब प्रदर्शन करेगा।
- IIF, CHOOSE, और COALESCE में गंदे रहस्य हैं। उन कार्यों के लिए मूल्यों को पारित करने से पहले इसे ध्यान में रखें। यह एक SQL केस में बदल जाएगा। मूल्यों के आधार पर, आप या तो त्रुटि या प्रदर्शन दंड का कारण बनते हैं।
मुझे उम्मीद है कि एसक्यूएल केस पर यह अलग टेक आपके लिए उपयोगी रहा है। यदि हां, तो आपके डेवलपर मित्र भी इसे पसंद कर सकते हैं। कृपया इसे अपने पसंदीदा सोशल मीडिया प्लेटफॉर्म पर साझा करें। और हमें कमेंट सेक्शन में बताएं कि आप इसके बारे में क्या सोचते हैं।