SQL सर्वर तदर्थ प्रश्नों के लिए निष्पादन योजनाओं को कैश करता है, इसलिए (पहली कॉल द्वारा लिए गए समय की छूट) गति के मामले में दो दृष्टिकोण समान होंगे।
सामान्य तौर पर, संग्रहीत कार्यविधियों के उपयोग का अर्थ है आपके एप्लिकेशन (टी-एसक्यूएल क्वेरीज़) के लिए आवश्यक कोड का एक हिस्सा लेना और इसे ऐसे स्थान पर रखना जो स्रोत नियंत्रण के अधीन नहीं है (यह कर सकता है हो, लेकिन आमतौर पर नहीं ) और जहां इसे आपकी जानकारी के बिना दूसरों द्वारा बदला जा सकता है।
इस तरह के केंद्रीय स्थान पर प्रश्नों का होना हो सकता है एक अच्छी बात हो, यह इस बात पर निर्भर करता है कि कितने अलग-अलग अनुप्रयोगों को उनके द्वारा प्रतिनिधित्व किए जाने वाले डेटा तक पहुंच की आवश्यकता है। मुझे आमतौर पर एप्लिकेशन निवासी द्वारा उपयोग किए गए प्रश्नों को एप्लिकेशन कोड में ही रखना बहुत आसान लगता है।
1990 के दशक के मध्य में, पारंपरिक ज्ञान ने कहा कि SQL सर्वर में संग्रहीत कार्यविधियाँ प्रदर्शन-महत्वपूर्ण स्थितियों में जाने का रास्ता थीं, और उस समय वे निश्चित रूप से थीं। हालांकि, इस सीडब्ल्यू के पीछे के कारण लंबे समय से मान्य नहीं हैं।
अपडेट करें: इसके अलावा, अक्सर संग्रहीत प्रक्रियाओं की व्यवहार्यता पर बहस में, एसक्यूएल इंजेक्शन को रोकने की आवश्यकता को प्रोसेस की रक्षा में लागू किया जाता है। निश्चित रूप से, उनके सही दिमाग में कोई भी नहीं सोचता है कि स्ट्रिंग कॉन्सटेनेशन के माध्यम से तदर्थ प्रश्नों को इकट्ठा करना सही काम है (हालाँकि यह आपको केवल SQL इंजेक्शन हमले के लिए उजागर करेगा यदि आप उपयोगकर्ता इनपुट को जोड़ रहे हैं। ) स्पष्ट रूप से तदर्थ प्रश्नों को पैरामीटरकृत किया जाना चाहिए, न केवल एक एसक्यूएल इंजेक्शन हमले के राक्षस-अंडर-द-बेड को रोकने के लिए, बल्कि प्रोग्रामर के रूप में अपने जीवन को आम तौर पर आसान बनाने के लिए (जब तक कि आपको यह पता लगाने में आनंद न आए कि एकल का उपयोग कब करना है) आपके मूल्यों के आसपास उद्धरण)।
अपडेट 2: मैंने और अधिक शोध किया है। इस MSDN श्वेत पत्र पर आधारित , ऐसा प्रतीत होता है कि उत्तर आपके प्रश्नों के साथ "तदर्थ" से आपका क्या मतलब है, इस पर निर्भर करता है। उदाहरण के लिए, इस तरह की एक साधारण क्वेरी:
SELECT ID, DESC FROM tblSTUFF WHERE ITEM_COUNT > 5
... होगा इसकी निष्पादन योजना कैश की गई है। इसके अलावा, क्योंकि क्वेरी में कुछ अयोग्य तत्व शामिल नहीं हैं (जैसे एक टेबल से साधारण चयन के अलावा लगभग कुछ भी), SQL सर्वर वास्तव में क्वेरी को "ऑटो-पैरामीटराइज़" करेगा और शाब्दिक स्थिरांक "5" को एक पैरामीटर और कैश से बदल देगा। पैरामीटरयुक्त संस्करण के लिए निष्पादन योजना। इसका अर्थ यह है कि यदि आप इसे निष्पादित करते हैं तो तदर्थ क्वेरी:
SELECT ID, DESC FROM tblSTUFF WHERE ITEM_COUNT > 23
... यह कैश्ड निष्पादन योजना का उपयोग करने में सक्षम होगा।
दुर्भाग्य से, ऑटो-पैरामीटरीकरण के लिए अयोग्य क्वेरी तत्वों की सूची लंबी है (उदाहरण के लिए, DISTINCT
का उपयोग करना भूल जाएं। , TOP
, UNION
, GROUP BY
, OR
आदि), इसलिए आप वास्तव में प्रदर्शन के लिए इस पर भरोसा नहीं कर सकते।
यदि आपके पास एक "सुपर कॉम्प्लेक्स" क्वेरी है जो ऑटो-पैरामीटरीकृत नहीं होगी, जैसे:
SELECT ID, DESC FROM tblSTUFF WHERE ITEM_COUNT > 5 OR ITEM_COUNT < 23
... यह अभी भी क्वेरी के सटीक पाठ द्वारा कैश किया जाएगा, इसलिए यदि आपका एप्लिकेशन इस क्वेरी को समान शाब्दिक "हार्ड-कोडेड" मानों के साथ बार-बार कॉल करता है, तो पहले के बाद प्रत्येक क्वेरी कैश्ड निष्पादन योजना का पुन:उपयोग करेगी (और इस प्रकार एक संग्रहित खरीद के रूप में तेज़ हो)।
यदि शाब्दिक मान बदलते हैं (उदाहरण के लिए, देखे गए डेटा को फ़िल्टर या सॉर्ट करने जैसी उपयोगकर्ता क्रियाओं के आधार पर), तो क्वेरीज़ को कैशिंग से कोई लाभ नहीं होगा (सिवाय कभी-कभी जब वे गलती से हाल की क्वेरी से सटीक रूप से मेल खाते हैं)।
"तदर्थ" प्रश्नों के साथ कैशिंग से लाभ उठाने का तरीका उन्हें पैरामीटर बनाना है। इस तरह सी # में फ्लाई पर एक प्रश्न बनाना:
int itemCount = 5;
string query = "DELETE FROM tblSTUFF WHERE ITEM_COUNT > " +
itemCount.ToString();
गलत है। सही तरीका (ADO.Net का उपयोग करके) कुछ इस तरह होगा:
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlCommand com = new SqlCommand(conn);
com.CommandType = CommandType.Text;
com.CommandText =
"DELETE FROM tblSTUFF WHERE ITEM_COUNT > @ITEM_COUNT";
int itemCount = 5;
com.Parameters.AddWithValue("@ITEM_COUNT", itemCount);
com.Prepare();
com.ExecuteNonQuery();
}
क्वेरी में कोई शाब्दिक नहीं है और पहले से ही पूरी तरह से पैरामीटरयुक्त है, इसलिए समान पैरामीटरयुक्त कथन का उपयोग करने वाले बाद के प्रश्न कैश्ड योजना का उपयोग करेंगे (भले ही विभिन्न पैरामीटर मानों के साथ कॉल किया गया हो)। ध्यान दें कि यहां कोड वस्तुतः उसी कोड के समान है जिसका उपयोग आप किसी भी तरह से संग्रहीत प्रक्रिया को कॉल करने के लिए करेंगे (केवल अंतर कमांड टाइप और कमांड टेक्स्ट है), इसलिए यह कुछ हद तक नीचे आता है जहां आप उस क्वेरी का टेक्स्ट "लाइव" करना चाहते हैं "(आपके आवेदन कोड में या संग्रहीत प्रक्रिया में)।
अंत में, यदि "तदर्थ" प्रश्नों से आपका मतलब है कि आप गतिशील रूप से विभिन्न कॉलम, टेबल, फ़िल्टरिंग पैरामीटर और क्या नहीं के साथ क्वेरी बना रहे हैं, जैसे शायद ये:
SELECT ID, DESC FROM tblSTUFF WHERE ITEM_COUNT > 5
SELECT ID, FIRSTNAME, LASTNAME FROM tblPEEPS
WHERE AGE >= 18 AND LASTNAME LIKE '%What the`
SELECT ID, FIRSTNAME, LASTNAME FROM tblPEEPS
WHERE AGE >= 18 AND LASTNAME LIKE '%What the`
ORDER BY LASTNAME DESC
... तो आप बहुत ज्यादा नहीं इसे संग्रहीत कार्यविधियों के साथ करें (बिना EXEC
हैक जिसके बारे में विनम्र समाज में बात नहीं की जानी चाहिए), इसलिए यह मुद्दा विवादास्पद है।
अपडेट 3: यहाँ केवल वास्तव में अच्छा प्रदर्शन-संबंधी है एक संग्रहीत प्रक्रिया का उपयोग करने के लिए कारण (जो मैं वैसे भी सोच सकता हूं)। यदि आपकी क्वेरी लंबे समय से चल रही है, जहां निष्पादन योजना को संकलित करने की प्रक्रिया वास्तविक निष्पादन की तुलना में काफी अधिक समय लेती है, और क्वेरी को केवल बार-बार कहा जाता है (उदाहरण के लिए, मासिक रिपोर्ट की तरह), तो इसे एक संग्रहीत प्रक्रिया में डालने से हो सकता है SQL सर्वर को संकलित योजना को कैश में लंबे समय तक रखें ताकि वह अभी भी अगले महीने के आसपास हो। हालांकि, यह सच है या नहीं, मुझे मारता है।