क्वेरी संकलन और निष्पादन के दौरान, SQL सर्वर को यह पता लगाने में समय नहीं लगता है कि कोई UPDATE स्टेटमेंट वास्तव में कोई मान बदलेगा या नहीं। यह अनावश्यक होने पर भी अपेक्षित रूप से लेखन करता है।
जैसे परिदृश्य में
update table1 set col1 = 'hello'
आप सोच सकते हैं कि एसक्यूएल कुछ नहीं करेगा, लेकिन यह करेगा - यह सभी आवश्यक लेखन करेगा जैसे कि आपने वास्तव में मूल्य बदल दिया है। यह भौतिक तालिका (या संकुल अनुक्रमणिका) के साथ-साथ उस स्तंभ पर परिभाषित किसी भी गैर-संकुल अनुक्रमणिका दोनों के लिए होता है। यह भौतिक तालिकाओं/अनुक्रमणिकाओं को लिखता है, अनुक्रमणिका की पुनर्गणना करता है और लेन-देन लॉग लिखता है। बड़े डेटा सेट के साथ काम करते समय, केवल उन पंक्तियों को अपडेट करने के लिए बड़े प्रदर्शन लाभ होते हैं जो एक परिवर्तन प्राप्त करेंगे।
यदि हम इन लेखन के ऊपरी भाग से बचना चाहते हैं, जब आवश्यक नहीं है तो हमें अद्यतन करने की आवश्यकता की जांच करने के लिए एक तरीका तैयार करना होगा। अपडेट करने की आवश्यकता की जांच करने का एक तरीका यह होगा कि "कहां col <> 'hello'.
जैसा कुछ जोड़ा जाए।update table1 set col1 = 'hello' where col1 <> 'hello'
लेकिन यह कुछ मामलों में अच्छा प्रदर्शन नहीं करेगा, उदाहरण के लिए यदि आप एक तालिका में कई पंक्तियों के साथ कई कॉलम अपडेट कर रहे थे और उन पंक्तियों के केवल एक छोटे से सबसेट के वास्तव में उनके मान बदल गए होंगे। यह उन सभी स्तंभों पर फिर फ़िल्टर करने की आवश्यकता के कारण है, और गैर-समानता विधेय आमतौर पर अनुक्रमणिका खोज का उपयोग करने में सक्षम नहीं होते हैं, और तालिका और अनुक्रमणिका का ऊपरी भाग लिखता है और लेन-देन लॉग प्रविष्टियाँ जैसा ऊपर बताया गया है।
लेकिन एक EXISTS क्लॉज के साथ EXCEPT क्लॉज के संयोजन का उपयोग करके एक बेहतर विकल्प है। विचार यह है कि गंतव्य पंक्ति में मानों की तुलना मिलान स्रोत पंक्ति के मानों से की जाए ताकि यह निर्धारित किया जा सके कि वास्तव में किसी अद्यतन की आवश्यकता है या नहीं। नीचे संशोधित क्वेरी को देखें और EXISTS से शुरू होने वाले अतिरिक्त क्वेरी फ़िल्टर की जांच करें। ध्यान दें कि EXISTS क्लॉज के अंदर SELECT स्टेटमेंट्स में FROM क्लॉज नहीं है। वह हिस्सा विशेष रूप से महत्वपूर्ण है क्योंकि यह केवल एक अतिरिक्त निरंतर स्कैन और क्वेरी योजना में एक फ़िल्टर ऑपरेशन जोड़ता है (दोनों की लागत तुच्छ है)। तो आप जिस चीज के साथ समाप्त होते हैं वह यह निर्धारित करने के लिए एक बहुत ही हल्का तरीका है कि क्या पहली बार में एक अद्यतन की भी आवश्यकता है, अनावश्यक लिखने से बचने के लिए।
update table1 set col1 = 'hello'
/* AVOID NET ZERO CHANGES */
where exists
(
/* DESTINATION */
select table1.col1
except
/* SOURCE */
select col1 = 'hello'
)
जब आप किसी तालिका में सभी पंक्तियों के लिए एक मान को शाब्दिक मान के साथ अपडेट कर रहे हैं, तो यह मूल प्रश्न में सरल स्केनेरियो के लिए एक साधारण WHERE क्लॉज में अपडेट के लिए अत्यधिक जटिल बनाम चेकिंग दिखता है। हालाँकि, यह तकनीक बहुत अच्छी तरह से काम करती है यदि आप एक तालिका में कई कॉलम अपडेट कर रहे हैं, और आपके अपडेट का स्रोत एक और क्वेरी है और आप राइट्स और ट्रांजेक्शन लॉग प्रविष्टियों को कम करना चाहते हैं। यह <> के साथ हर क्षेत्र का परीक्षण करने से भी बेहतर प्रदर्शन करता है।
एक अधिक संपूर्ण उदाहरण हो सकता है
update table1
set col1 = 'hello',
col2 = 'hello',
col3 = 'hello'
/* Only update rows from CustomerId 100, 101, 102 & 103 */
where table1.CustomerId IN (100, 101, 102, 103)
/* AVOID NET ZERO CHANGES */
and exists
(
/* DESTINATION */
select table1.col1
table1.col2
table1.col3
except
/* SOURCE */
select z.col1,
z.col2,
z.col3
from #anytemptableorsubquery z
where z.CustomerId = table1.CustomerId
)