क्या केवल एक बार होने वाले WHERE क्लॉज में एक चर पर एक अशक्त जांच करने का कोई तरीका है?


12

मेरे पास एक बड़ी तालिका पर एक क्वेरी है जो इस तरह दिखती है:

declare @myIdParam int = 1

select * 
from myTable
where (@myIdParam is null or myTable.Id = @myIdParam)

इस तरह की कई स्थितियां हैं जहां खंड में, और बहुत सारे जोड़ भी हैं, लेकिन यह एक सारांश है।

प्रभावी रूप से, यदि @myIdParam शून्य है, तो हम इस पैरामीटर का उपयोग करके परिणामों को प्रतिबंधित नहीं करना चाहते हैं।

मैं एक DB समर्थक नहीं हूँ, लेकिन मेरे परीक्षणों से ऐसा लगता है कि यह NULL जाँच हर रिकॉर्ड के लिए की जाती है और किसी भी तरह से अनुकूलित नहीं है।

यदि मैं अशक्त जांच को हटा देता हूं और मान लेता हूं कि पैरामीटर अशक्त नहीं है, तो क्वेरी तुरंत लौट आती है। अन्यथा, इसमें दस सेकंड तक का समय लगता है।

क्या इसका अनुकूलन करने का कोई तरीका है ताकि चेक केवल एक बार रनटाइम पर किया जाए?


1
इस उत्तर को देखें: stackoverflow.com/questions/3415582/… tl; dr उपयोगOPTION(RECOMPILE)
vercelli

@vercelli यह ट्रिक करता है। इस प्रश्न पर विचार करना वास्तव में वैकल्पिक मापदंडों के बारे में है, मैं कहूंगा कि यह आपके द्वारा लिंक किए गए एक डुप्लिकेट है।
मिस्टागोग

शायद, लेकिन यह 6 साल पहले की पोस्ट है। शायद SqlServer 2014 या 2016 के साथ एक नया तरीका है। (मैंने 2014 में इसे बिना रीकैपाइल के परीक्षण किया और हमेशा के लिए ले लिया)
वर्सी

चूंकि आपकी वास्तविक क्वेरी में कई वैकल्पिक पैरामीटर हैं, इसलिए डायनेमिक SQL सर्वश्रेष्ठ प्रदर्शन प्रदान करेगा। विषय पर गहन लेख के लिए sommarskog.se/dyn-search.html देखें ।
डेन गुज़मैन

@DanGuzman के साथ RECOMPILE का उपयोग करते हुए प्रश्न के रूप में उल्लिखित कुलसचिव ने व्यावहारिक रूप से अत्यधिक चयनात्मक मानदंडों के साथ तुरंत एक मिनट के भीतर क्वेरी समय में कटौती की। मैं प्रदर्शन और पठनीयता को संतुलित करने के लिए इसे सबसे अच्छा विकल्प मानता हूं।
मिस्ट्रीगॉग

जवाबों:


8

एक तरीका डायनेमिक एसक्यूएल का उपयोग करना है, एक नल चेक का उपयोग करके वैकल्पिक रूप से उस हिस्से को जोड़ना है जहां क्लॉज है।

declare @myIdParam int = 1
declare @vc_dynamicsql varchar(max)

set @vc_dynamicsql = 'select * from myTable where 1=1'

if @myIdParam is not null
    set @vc_dynamicsql = @vc_dynamicsql + ' and  myTable.Id = @myIdParam'

EXECUTE sp_executesql @vc_dynamicsql

2
मैं वास्तव में ऐसा नहीं करना पसंद करूंगा, लेकिन यह एक समाधान है। मेरी आशा है कि कोई व्यक्ति बहुत बेहतर के साथ आता है।
15

1
यह खोज क्वेरी के इस वर्ग को संभालने का सबसे अच्छा तरीका है। Stackoverflow जवाब @vercelli से जाना जाता ऐसा करने के तरीके के लिए महान संदर्भ शामिल हैं।
मैक्स वेरनॉन

यह सबसे अच्छा तरीका है लेकिन मैंने नोटिस किया कि @params पैरामीटर sp_ExecuteSQLगायब है और @vc_dynamicsqlपैरामीटर के लिए a होना चाहिए NVARCHAR
जेम्स एंडरसन

4

किसी भी समय आप एक स्तंभ के चारों ओर एक फ़ंक्शन डालते हैं उदाहरण के लिए 'ISNULL (@var, table.col)' आप एक सूचकांक का उपयोग करने के लिए SQL की क्षमता को हटाते हैं। यदि आप इसे एक क्वेरी में रखना चाहते हैं तो यह वास्तव में सबसे अच्छा प्रदर्शन करने वाला विकल्प है।

@var IS NULL or @var = table.col

अन्यथा आपके पास दो विकल्प हैं। पहला गतिशील एसक्यूएल है और @ मिस्टागोग का उत्तर इसके लिए पर्याप्त है अन्यथा आप इस तरह दो प्रश्नों में डाल सकते हैं:

IF @var is NULL
     SELECT * FROM table
ELSE
     SELECT * FROM table WHERE @var = col

इस प्रारूप और गतिशील एसक्यूएल दोनों में आपको वास्तव में प्रत्येक क्वेरी के लिए एक अलग क्वेरी प्लान मिलेगा (जो संभावित रूप से बेहतर प्रदर्शन देगा)।


प्रश्न में Sql ISNULL या किसी अन्य फ़ंक्शन का उपयोग नहीं कर रहा है।
मिस्टागोग

@MystagogueI मैं अब हटाए गए उत्तर का उल्लेख कर रहा था।
केनेथ फिशर

0

खैर, आप कर सकते हैं:

declare @myIdParam int = 1;

select *
from myTable
where nullif(@myIdParam, myTable.Id) is null;

हालांकि, ध्यान रखें कि nullif()फ़ंक्शन अनिवार्य रूप से एक आवरण पर है case। यह एक चांदी की गोली नहीं है जो जादुई रूप से समाप्त हो जाती है ORऔर इस तरह क्वेरी को गति देती है।


जहां क्लॉज में फंक्शंस का उपयोग करने से प्रदर्शन पर नकारात्मक प्रभाव पड़ता है क्योंकि यह अनुक्रमित (या तो मैंने सुना है) के उपयोग को रोकता है
मिस्टागोगाम

@ मिस्टागोग, हाँ - यह आमतौर पर खोज की स्थिति को गैर-SARGable बनाता है। काश, यह एकमात्र तरीका है जो मुझे पता है कि डायनेमिक एसक्यूएल या मल्टीपल UNIONएस का सहारा लिए बिना आपके प्रश्न का उत्तर कैसे दिया जाए । जब मेरे पास यह सटीक कार्य था, तो मैंने डायनेमिक एसक्यूएल चुना।
रोजर वुल्फ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.