फ़िल्टर्ड खोज को कार्यान्वित करने के लिए सर्वोत्तम विधि


17

जब आप फ़िल्टर किए गए खोज फ़ॉर्म को लागू करने की बात करते हैं, तो मैं आपसे, आपकी राय पूछना चाहूंगा। आइए निम्नलिखित मामले की कल्पना करें:

  • 1 कॉलम की बहुत सी बड़ी तालिका
  • यह कहना महत्वपूर्ण हो सकता है कि यह SQL सर्वर

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

अब मेरा प्रश्न यहाँ है कि खोज को लागू करने के लिए निम्नलिखित में से कौन सा तरीका सबसे अच्छा होना चाहिए?

  1. किसी क्वेरी के साथ एक संग्रहीत कार्यविधि बनाएं। यह संग्रहीत कार्यविधि यह जांच करेगी कि क्या पैरामीटर आवेदन द्वारा दिए गए हैं और मामले में उन्हें वाइल्डकार्ड नहीं दिया गया है, उन्हें क्वेरी में डाल दिया जाएगा।

  2. एक डायनामिक क्वेरी बनाएं, जो कि एप्लिकेशन द्वारा दिए गए अनुसार बनाई गई हो।

मैं यह पूछ रहा हूं क्योंकि मुझे पता है कि SQL सर्वर एक निष्पादन योजना बनाता है जब संग्रहीत कार्यविधि बनाई जाती है, ताकि उसके प्रदर्शन को अनुकूलित किया जा सके, हालांकि संग्रहीत कार्यविधि के अंदर एक गतिशील क्वेरी बनाने से हम निष्पादन योजना द्वारा प्राप्त अनुकूलन का बलिदान करेंगे?

कृपया मुझे बताएं कि आपके उत्पीड़न में सबसे अच्छा तरीका क्या होगा।


आप नीचे बता रहे हैं कि आप गतिशील समाधान की ओर बढ़ रहे हैं। यह अच्छा है, बस यह सुनिश्चित करें कि आप संभावित फ़िल्टर को एनुमरेट करें और उन्हें समर्थन करने वाले अनुक्रमित करें। इसलिए जब तक प्रश्नों को लगातार बनाया जाता है, तब तक उन्हें कुशल होना चाहिए।
मैथ्यू फ्लिन

जवाबों:


10

आप इसी तरह के सवाल का जवाब यहां देखना चाहते हैं: /programming/11329823/add-where-clauses-to-sql-dynamically-programmatically

हमने पाया है कि एक SPROC जो वैकल्पिक मापदंडों का एक गुच्छा लेता है और इस तरह से फ़िल्टर को लागू करता है:

CREATE PROC MyProc (@optionalParam1 NVARCHAR(50)=NULL, @optionalParam2 INT=NULL)
AS 
...
SELECT field1, field2, ... FROM [Table]
WHERE 
  (@optionalParam1 IS NULL OR MyColumn1 = @optionalParam1)
  AND (@optionalParam2 IS NULL OR MyColumn2 = @optionalParam2)

पहली क्रियान्वयन योजना को कैश करेगा (उदाहरण के लिए @optionalParam1 = 'Hello World', @optionalParam2 = NULL) लेकिन अगर हम इसे वैकल्पिक मापदंडों (जैसे @optionalParam1 = NULL, @optionalParam2 = 42) के एक अलग सेट से गुजारें तो यह गलत होगा । (और जाहिर है हम कैश्ड प्लान का प्रदर्शन चाहते हैं, इसलिए WITH RECOMPILEबाहर है)

यहां अपवाद यह है कि यदि वैकल्पिक पैरामीटर के अलावा, क्वेरी पर कम से कम एक MANDATORY फ़िल्टर है जो अत्यधिक चयनात्मक और ठीक अनुक्रमित है, तो उपरोक्त PROC ठीक प्रदर्शन करेगा।

हालाँकि, यदि सभी फ़िल्टर वैकल्पिक हैं, बल्कि भयानक सत्य यह है कि पैरामीटराइज्ड डायनामिक sql वास्तव में बेहतर प्रदर्शन करता है (जब तक कि आप N नहीं लिखते हैं। वैकल्पिक मापदंडों के प्रत्येक क्रमपरिवर्तन के लिए अलग-अलग स्थैतिक PROCS)।

नीचे की तरह गतिशील एसक्यूएल क्वेरी मापदंडों के प्रत्येक क्रमपरिवर्तन के लिए एक अलग योजना बनाएगा और कैश करेगा, लेकिन कम से कम प्रत्येक योजना विशिष्ट क्वेरी के लिए 'अनुरूप' होगी (इससे कोई फर्क नहीं पड़ता कि यह एक पीआरसी या एडहॉक एसक्यूएल है - जैसा कि जब तक वे प्रश्नों के पैरामीटर हैं, उन्हें कैश किया जाएगा)

तो इसलिए मेरी प्राथमिकता:

DECLARE @SQL NVARCHAR(MAX)        

-- Mandatory / Static part of the Query here
SET @SQL = N'SELECT * FROM [table] WHERE 1 = 1'

IF @OptionalParam1 IS NOT NULL        
    BEGIN        
        SET @SQL = @SQL + N' AND MyColumn1 = @optionalParam1'    
    END        

IF @OptionalParam2 IS NOT NULL        
    BEGIN        
        SET @SQL = @SQL + N' AND MyColumn2 = @optionalParam2'    
    END        

EXEC sp_executesql @SQL,        
    N'@optionalParam1 NVARCHAR(50), 
      @optionalParam2 INT'
    ,@optionalParam1 = @optionalParam1
    ,@optionalParam2 = @optionalParam2

आदि। यदि हम अनावश्यक मानकों को sp_executesql में पास करते हैं तो कोई बात नहीं है - उन्हें नजरअंदाज कर दिया जाता है। यह ध्यान देने योग्य है कि ORM जैसे Linq2SQL और EF एक समान तरीके से पैरामीटराइज्ड डायनामिक sql का उपयोग करते हैं।


1
हाँ मुझे ऐसा लगा, यह विकल्प था जो मैं चुनता हूं। बस यह सुनिश्चित करना चाहता था कि यह एक अच्छा था। आपके उत्तर के लिए धन्यवाद।
j0N45

"यदि किसी SQL कथन को मापदंडों के बिना निष्पादित किया जाता है, तो SQL सर्वर कथन को मौजूदा निष्पादन योजना के विरुद्ध मिलान की संभावना को बढ़ाने के लिए आंतरिक रूप से मापता है। इस प्रक्रिया को साधारण पैरामीटर कहा जाता है।" तो मूल रूप से प्रोग्राम कुछ चीज़ जैसे "जहाँ फ़ाइलन =" + फ़ाइलनाम का उपयोग कर सकता है। बेशक, कि कीड़े के एक डिब्बे को खोलता है, लेकिन यह एक अलग विषय है ;-)
कोडवाद

5

जो भी आपको लगता है कि इसे लागू करना आसान है (मुझे लगता है कि विकल्प 2) से शुरू करें। फिर वास्तविक विश्व डेटा के लिए प्रदर्शन को मापें । केवल जरूरत पड़ने पर ही अनुकूलन करना शुरू करें, पहले से नहीं।

वैसे, आपके खोज फ़िल्टर कितने जटिल हैं, इस आधार पर, आपका कार्य आसानी से गतिशील SQL के बिना हल नहीं हो सकता है। इसलिए जब आप एक संग्रहीत कार्यविधि का उपयोग करते हैं, तब भी संभवतः प्रदर्शन में वृद्धि नहीं होगी, जैसा कि आप पहले से ही संदेह कर रहे हैं। दूसरी ओर, यदि यह मदद करता है, तो कई प्रकार के संकेत हैं (देखें http://www.simple-talk.com/sql/performance/controlling-execution-plans-with-hints/ ) जिसे आप SQL में जोड़ सकते हैं क्वेरी, डायनेमिक या नहीं, SQL सर्वर को उसकी निष्पादन योजना को अनुकूलित करने में मदद करने के लिए।


खैर, मैंने पहले ही विकल्प 2 को लागू कर दिया है और मुझे लगता है कि यह जाने का सबसे अच्छा तरीका है, मुख्यतः क्योंकि वाइल्डकार्ड नाटकीय रूप से प्रदर्शन को कम कर देंगे, हालांकि मैं रखरखाव की बलि दे रहा हूं, क्योंकि इससे कोड में जटिलता बढ़ जाएगी। मैं सिर्फ यह जानना चाहता था कि क्या कोई इस तरह की स्थितियों के लिए बेहतर विकल्प जानता है।
j0N45

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