2010-01-29 25 views
5

के साथ प्रयुक्त "OR" खंड के उपयोग को अनुकूलित करने के लिए कैसे करें मुझे आश्चर्य है कि निम्न क्वेरी को फिर से लिखने का कोई बुद्धिमान तरीका है ताकि स्तंभों पर अनुक्रमणिका ऑप्टिमाइज़र द्वारा उपयोग की जाए?पैरामीटर (SQL सर्वर 2008)

Create Procedure select_Proc1 
    @Key1 int=0, 
    @Key2 int=0 
As 
BEGIN 
    Select key3 
    From Or_Table 
    Where (@key1 =0 OR Key1 [email protected]) AND 
      (@key2 =0 OR Key2 [email protected]) 
END 
GO 

हालांकि कहां खंड में स्तंभों अनुक्रमित के अंतर्गत आते हैं, एसक्यूएल सर्वर इन अनुक्रमित उपयोग करने में असमर्थ है। यह सवाल उठाता है कि क्या कुछ भी इंडेक्स के उपयोग को अवरुद्ध कर रहा है या नहीं। इस सवाल का जवाब हां है - अपराधी पैरामीटर और "OR" स्थिति हैं। पैरामीटर इंडेक्स द्वारा कवर नहीं होते हैं, जिसका अर्थ है कि SQL सर्वर किसी भी इंडेक्स का उपयोग "@ key1 = 0" (एक शर्त जो @ key2 = 0 पर भी लागू होता है) का मूल्यांकन करने के लिए नहीं कर सकता है। प्रभावी रूप से, इसका मतलब है कि SQL सर्वर खंड "@ key1 = 0 या key1 = @ key1" का मूल्यांकन करने के लिए इंडेक्स का उपयोग नहीं कर सकता है (जैसा कि "OR" खंड दोनों स्थितियों से कवर पंक्तियों का संघ है)। वही सिद्धांत अन्य खंड (पुनः कुंजी 2) पर भी लागू होता है। इससे SQL सर्वर को यह निष्कर्ष निकाला जा सकता है कि पंक्तियों को निकालने के लिए कोई अनुक्रमणिका का उपयोग नहीं किया जा सकता है, जिससे SQL सर्वर को अगले सर्वोत्तम दृष्टिकोण का उपयोग करने के लिए छोड़ दिया जा सकता है - क्लस्टरर्ड इंडेक्स स्कैन

जैसा कि आप देखते हैं, SQL अनुकूलक कॉलम पर अनुक्रमणिका का उपयोग नहीं करेगा यदि भविष्यवाणियां WHERE खंड में "OR" ed हैं। इस समस्या का एक समाधान, पैरामीटर के सभी संभावित संयोजन के लिए IF खंड के साथ प्रश्नों को अलग करना है।

कृपया समस्या का एक बेहतर दृश्य प्राप्त करने इस छोटे से लेख पढ़ें: http://www.sql-server-performance.com/articles/per/optimize_or_clause_p1.aspx

अब मेरे सवाल है, हमें क्या करना चाहिए संभावित संयोजन हैं, तो अधिक है कि बस तीन या चार? प्रत्येक संयोजन के लिए एक अलग क्वेरी लिखना एक तर्कसंगत समाधान प्रतीत नहीं होता है। क्या इस समस्या के लिए कोई और कामकाज है?

उत्तर

11

SQL ServerOR भविष्यवाणियों को अनुकूलित करने में बहुत अच्छा नहीं है।

इस का उपयोग करें:

SELECT key3 
FROM or_table 
WHERE @key1 = 0 
     AND @key2 = 0 
UNION ALL 
SELECT key3 
FROM or_table 
WHERE @key1 = 0 
     AND @key2 <> 0 
     AND key2 = @key2 
UNION ALL 
SELECT key3 
FROM or_table 
WHERE @key2 = 0 
     AND @key1 <> 0 
     AND key1 = @key1 
UNION ALL 
SELECT key3 
FROM or_table 
WHERE @key1 <> 0 
     AND @key2 <> 0 
     AND key1 = @key1 
     AND key2 = @key2 

SQL Server चर प्रश्नों को क्रियान्वित करने से पहले के मूल्यों को दिखेगा और अनावश्यक क्वेरी का उपयोग करके अनुकूलित करेंगे।

इसका मतलब है कि चार की केवल एक क्वेरी वास्तव में निष्पादित की जाएगी।

+0

दिलचस्प दृष्टिकोण, मुझे लगता है कि याद रखना होगा। मुझे लगता है कि यह अन्य आरडीबीएमएस जैसे ओरेकल पर भी लागू होगा, जहां 'OR' बहुत अक्षम है। – Lucero

+1

क्या यह एकमात्र तरीका है? क्या होगा यदि क्वेरी अधिक जटिल है (अधिक या खंड शामिल हैं) – Meysam

3

MSSQL 2008, हालत सरलीकरण के अनुकूलन वाक्यविन्यास है यहाँ यह है

Where (@key1 =0 OR Key1 [email protected]) AND 
     (@key2 =0 OR Key2 [email protected]) option(recompile) 

यह स्थिरांक

+0

मुझे नहीं लगता कि इससे मदद मिलती है। यह केवल तब काम करेगा जब हम पैरामीटर स्नीफिंग समस्या से निपट रहे हैं। – Meysam

2

आप एक तालिका महत्वपूर्ण अवसर हैं समारोह के उपयोग का अनुकूलन होगा?

CREATE FUNCTION select_func1 ( 
    @Key1 int=0, 
    @Key2 int=0 
) 
RETURNS TABLE 
AS RETURN (
    Select key3 
    From Or_Table 
    Where (@key1 =0 OR Key1 [email protected]) AND 
      (@key2 =0 OR Key2 [email protected]) 
) 


select * from select_func1(1,2) 
+0

ओएमजी! जैसा कि मैं निष्पादन योजना में देख सकता हूं, तालिका-मूल्यवान फ़ंक्शन का उपयोग करते समय इंडेक्स का उपयोग किया जा रहा है! अंतर क्या है?! क्या आप इसे समझा सकते हैं ?! – Meysam

+0

प्रत्येक तालिका का उपयोग किए जाने पर एक तालिका मूल्यवान फ़ंक्शन का मूल्यांकन किया जाता है (एक दृश्य की तरह)। इसका अर्थ यह है कि ऑप्टिमाइज़र क्वेरी प्लान बनाने से पहले पैरामीटर का मूल्यांकन करने में सक्षम होगा। आप बाहरी क्वेरी में उन्नत टेक्स्ट मैक्रोज़ के रूप में तालिका मूल्यवान कार्यों को देख सकते हैं। – adrianm

+0

ओह, अभी भी आपके दृष्टिकोण में कोई समस्या है। यदि आप चर पैरामीटर के साथ फ़ंक्शन कॉल में निरंतर पैरामीटर को प्रतिस्थापित करते हैं, तो फिर अनुक्रमणिका का उपयोग नहीं किया जाता है। इस तरह कुछ: select_func1 से चुनें * (@ key1, @ key2) – Meysam

0

हाँ - गतिशील एसक्यूएल से सावधान उपयोग इस समस्या का समाधान होगा। ऐसा करने के दो तरीके हैं:

ए। यदि आप संग्रहीत प्रोसेस के बारे में "शुद्ध" हैं, तो एक संग्रहित प्रो के अंदर एक कस्टम क्वेरी स्ट्रिंग लिखें और स्ट्रिंग निष्पादित करें। तब विशिष्ट क्वेरी को केवल प्रासंगिक मानदंडों को शामिल करने के लिए गतिशील रूप से प्रति निष्पादन लिखा जा सकता है।

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

खतरे, ज़ाहिर है, एसक्यूएल इंजेक्शन के आसपास है। तो आपको बहुत सावधान रहना होगा कि क्लाइंट से गतिशील एसक्यूएल कथन में डेटा कैसे पारित किया जाता है। Erland Sommarskog से

व्यापक जानकारी: http://www.sommarskog.se/dynamic_sql.html और http://www.sommarskog.se/dyn-search.html