एसक्यूएल स्टेटमेंट क्या सारगर्भित बनाता है?


252

परिभाषा के अनुसार (कम से कम मैंने जो देखा है) सारगर्भित का मतलब है कि एक क्वेरी क्वेरी इंजन के निष्पादन की योजना को अनुकूलित करने में सक्षम है जो क्वेरी का उपयोग करता है। मैंने उत्तर देखने की कोशिश की है, लेकिन विषय वस्तु पर बहुत कुछ नहीं लगता है। तो सवाल यह है कि एसक्यूएल क्वेरी को व्यर्थ करने या न करने से क्या होता है? किसी भी प्रलेखन बहुत सराहना की जाएगी।

संदर्भ के लिए: SARGable


58
"Sargable" के लिए +1। आज के लिए मेरा दिन का शब्द है। :-p
BFree

1
मैं एडम के जवाब में यह भी जोड़ सकता हूं कि जानकारी के पहाड़ ज्यादातर मामलों में प्रत्येक डीबी इंजन के लिए विशेष रूप से हैं।
होअगी

30
SARG = खोज ARGument। मजेदार बात यह है: जर्मन में "SARG" का अर्थ "ताबूत" है, इसलिए मुझे हमेशा मुस्कुराना पड़ता है जब लोग SARGABLE के बारे में बात करते हैं - एक ताबूत में रखा जा सकता है? :-)
२०:३०

sargability आपके वातावरण पर निर्भर करती है। MySQL का यहां दस्तावेज है: dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
फ्रैंक किसान

"लुकअप टेबल" के बजाय फ़्री-टेक्स्ट फ़ील्ड रखने से क्वेरी क्वेरी करने की भावना के विरुद्ध भी जाती है। फ्री-टेक्स्ट (जैसे शहर का नाम) दर्ज करते समय उपयोगकर्ता सामान छोड़ देते हैं, जबकि लुक-टेबल उपयोगकर्ताओं को एक सही ढंग से वर्तनी प्रविष्टि चुनने के लिए मजबूर करते हैं। अच्छी तरह से थोड़ी अतिरिक्त परेशानी के लायक है, क्योंकि यह विधेय में '% ...%' का उपयोग करने के बजाय ठीक से अनुक्रमित किया जा सकता है।
उल्टा इंजीनियर

जवाबों:


256

सबसे सामान्य बात जो एक प्रश्न को गैर-सारगर्भित बना देगी, वह यह है कि किसी फ़ंक्शन के अंदर फ़ील्ड को उस खंड में शामिल करना है:

SELECT ... FROM ...
WHERE Year(myDate) = 2008

SQL ऑप्टिमाइज़र myDate पर एक इंडेक्स का उपयोग नहीं कर सकता है, भले ही कोई मौजूद हो। यह शाब्दिक रूप से तालिका की प्रत्येक पंक्ति के लिए इस फ़ंक्शन का मूल्यांकन करना होगा। उपयोग करने के लिए बेहतर है:

WHERE myDate >= '01-01-2008' AND myDate < '01-01-2009'

कुछ अन्य उदाहरण:

Bad: Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'
Fixed: Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))

Bad: Select ... WHERE SUBSTRING(DealerName,4) = 'Ford'
Fixed: Select ... WHERE DealerName Like 'Ford%'

Bad: Select ... WHERE DateDiff(mm,OrderDate,GetDate()) >= 30
Fixed: Select ... WHERE OrderDate < DateAdd(mm,-30,GetDate()) 

7
क्या किसी कार्य के अंदर GROUP BYकोई क्वेरी गैर-योग्य होने के कारण शामिल होगी?
माइक बेली

1
कुछ डेटाबेस इंजन (Oracle, PostgreSQL) भावों पर अनुक्रमणिका का समर्थन करते हैं, न ही पता है?
क्रेग

3
एक बेहतर संस्करण WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))होगा SELECT... FROM ... WHERE FullName = 'Ed Jones' UNION SELECT...FROM...WHERE FullName IS NULL? मुझे एक बार एक ऑप्टिमाइज़ेशन लड़के ने बताया था कि OR का उपयोग करके जहाँ क्लॉज़ प्रश्नों को अनसुना कर सकता है ..?
हाई प्लेन्स ग्रिफ्टर

2
@HighPlainsGrifter आपको उस क्वेरी पर एक UNION ALL का उपयोग करना चाहिए - संघ में एक निहित विशिष्ट है, जो किसी क्वेरी को उस समय की तुलना में अधिक महंगा बनाता है जब आपको पारस्परिक रूप से अनन्य डेटासेट्स की आवश्यकता होती है
डेविन लैमोथेले

1
@BradC MSSQL 2016 में, कोई निष्पादन योजना अंतर नहीं है Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'और Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))। वे दोनों FullName पर सूचकांक का उपयोग करते हैं और एक सूचकांक की तलाश करते हैं।
CEGRD

79

ऐसा न करें:

WHERE Field LIKE '%blah%'

यह एक टेबल / इंडेक्स स्कैन का कारण बनता है, क्योंकि LIKE मान वाइल्डकार्ड वर्ण से शुरू होता है।

ऐसा न करें:

WHERE FUNCTION(Field) = 'BLAH'

यह एक टेबल / इंडेक्स स्कैन का कारण बनता है।

डेटाबेस सर्वर को तालिका में हर पंक्ति के खिलाफ FUNCTION () का मूल्यांकन करना होगा और फिर उसकी तुलना 'BLAH' से करनी होगी।

यदि संभव हो तो, इसे उल्टा करें:

WHERE Field = INVERSE_FUNCTION('BLAH')

यह पैरामीटर के खिलाफ एक बार INVERSE_FUNCTION () चलाएगा और अभी भी सूचकांक के उपयोग की अनुमति देगा।


5
फ़ंक्शन को फ़्लिप करने के साथ आपका सुझाव वास्तव में केवल तभी काम करेगा जब फ़ंक्शन राउंड-ट्रिप डेटा (जिसका अर्थ है कि f (f (n)) = n)।
एडम रॉबिन्सन

5
सच। मैंने INVERSE_FUNCTION को जोड़ने पर विचार किया लेकिन भ्रमित नहीं होना चाहता था। मैं इसे बदल दूंगा।
समुद्रतट

9

इस जवाब में मुझे लगता है कि डेटाबेस में पर्याप्त कवरिंग इंडेक्स हैं। इस विषय में पर्याप्त प्रश्न हैं

संबंधित क्वेरी के टिपिंग पॉइंट द्वारा किसी क्वेरी की सारगर्भिता का कई बार निर्धारण किया जाता है। टिपिंग बिंदु एक तालिका में शामिल होने या दूसरे पर सेट किए गए परिणाम को शामिल करते समय सूचकांक की मांग और स्कैनिंग के बीच के अंतर को परिभाषित करता है। एक मेज पूरी तरह से स्कैन करने की तुलना में बहुत तेजी से होती है, लेकिन जब आपको बहुत सी पंक्तियों की तलाश करनी होती है, तो एक स्कैन अधिक समझ में आता है।

अन्य बातों के अलावा, जब एसक्यूएल कथन अधिक सारगर्भित होता है, जब आशावादी को एक तालिका की परिणामी पंक्तियों की संख्या अगले तालिका पर संभावित सूचकांक के टिपिंग बिंदु से कम होने की उम्मीद होती है।

आप एक विस्तृत पोस्ट और उदाहरण यहां पा सकते हैं ।


4

किसी ऑपरेशन को व्यर्थ माना जाना चाहिए, इसके लिए केवल एक मौजूदा सूचकांक का उपयोग करने में सक्षम होना पर्याप्त नहीं है। ऊपर दिए गए उदाहरण में, जहां खंड में एक अनुक्रमित स्तंभ के खिलाफ एक फ़ंक्शन कॉल को जोड़ना, अभी भी सबसे अधिक संभावना है कि परिभाषित सूचकांक का कुछ फायदा होगा। यह "स्कैन" करेगा उर्फ ​​उस कॉलम (इंडेक्स) से सभी मानों को पुनः प्राप्त करता है और फिर उन लोगों को समाप्त करता है जो प्रदान किए गए फ़िल्टर मूल्य से मेल नहीं खाते हैं। यह उच्च पंक्तियों वाली तालिकाओं के लिए अभी भी पर्याप्त कुशल नहीं है। क्या वास्तव में sargability को परिभाषित करता है द्वि-खोज विधि का उपयोग करके बी-ट्री इंडेक्स को पार करने की क्वेरी क्षमता है जो सॉर्ट किए गए आइटम सरणी के लिए आधे-सेट उन्मूलन पर निर्भर करता है। SQL में, इसे "इंडेक्स सीक" के रूप में निष्पादन योजना पर प्रदर्शित किया जाएगा।

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