समस्या यह नहीं है कि DISTINCT पैरामीटर के साथ प्रदर्शन में गिरावट का कारण बन रहा है, यह है कि शेष क्वेरी को पैरामीटरयुक्त क्वेरी में अनुकूलित नहीं किया जा रहा है क्योंकि ऑप्टिमाइज़र केवल [email protected] _ADMINISTRATOR इसे केवल 1=1 के साथ पसंद करेगा। यह बिना के जॉइन को ऑप्टिमाइज़ नहीं करेगा विशिष्ट क्योंकि इसे जुड़ने के परिणाम के आधार पर डुप्लिकेट वापस करने की आवश्यकता होती है।
क्यों? क्योंकि सभी जॉइन को बाहर करने वाली निष्पादन योजना @IS_ADMINISTRATOR =1 के अलावा किसी भी मूल्य के लिए अमान्य होगी। यह उस योजना को कभी भी उत्पन्न नहीं करेगा चाहे आप कैशिंग योजनाएं हों या नहीं।
यह मेरे 2008 सर्वर पर गैर-पैरामीटरयुक्त क्वेरी के साथ-साथ निष्पादित करता है:
-- PARAMETRIZED QUERY
declare @IS_ADMINISTRATOR int
declare @User_ID int
set @IS_ADMINISTRATOR = 1 -- 1 for administrator 0 for normal
set @User_ID = 50
IF 1 = @IS_ADMINISTRATOR
BEGIN
SELECT DISTINCT -- PLEASE REMEMBER DISTINCT MAKES THE DIFFERENCE!!!
DOC.DOCUMENT_ID
FROM
DOCUMENTS DOC LEFT OUTER JOIN
FOLDERS FOL ON FOL.FOLDER_ID = DOC.FOLDER_ID LEFT OUTER JOIN
ROLES ROL ON (FOL.FOLDER_ID = ROL.FOLDER_ID)
WHERE
1 = 1
END
ELSE
BEGIN
SELECT DISTINCT -- PLEASE REMEMBER DISTINCT MAKES THE DIFFERENCE!!!
DOC.DOCUMENT_ID
FROM
DOCUMENTS DOC LEFT OUTER JOIN
FOLDERS FOL ON FOL.FOLDER_ID = DOC.FOLDER_ID LEFT OUTER JOIN
ROLES ROL ON (FOL.FOLDER_ID = ROL.FOLDER_ID)
WHERE
ROL.USER_ID = @USER_ID
END
आपके उदाहरण को चलाने के लिए मुझे जो क्वेरी योजना दिखाई दे रही है, उससे यह स्पष्ट है कि @IS_ADMINISTRATOR = 1
1=1
. के समान अनुकूलित नहीं होता है . आपके गैर-पैरामीटरयुक्त उदाहरण में, जॉइन पूरी तरह से अनुकूलित हैं, और यह केवल दस्तावेज़ तालिका में प्रत्येक आईडी लौटाता है (बहुत आसान)।
@IS_ADMINISTRATOR <> 1
. के दौरान अलग-अलग अनुकूलन भी गायब हैं . उदाहरण के लिए, LEFT OUTER JOIN
S स्वचालित रूप से INNER JOIN
में बदल जाते हैं रों बिना वह OR
खंड, लेकिन उन्हें साथ . के रूप में छोड़ दिया गया है वह या खंड।
यह उत्तर भी देखें:SQL LIKE% FOR INTEGERS एक गतिशील SQL विकल्प के लिए।
बेशक, यह वास्तव में आपके मूल प्रश्न में प्रदर्शन अंतर की व्याख्या नहीं करता है, क्योंकि आपके पास OR नहीं है। मुझे लगता है कि यह एक भूल थी।