2014-05-05 6 views
9

असल में मुझे यकीन नहीं है कि शीर्षक सटीक रूप से प्रश्न का वर्णन करता है, लेकिन मुझे उम्मीद है कि यह काफी करीब है।SQLDataReader वास्तव में बड़ी क्वेरी कैसे संभालता है?

मेरे पास कुछ कोड है जो डेटाबेस तालिका से एक चयन करता है जो मुझे पता है जिसके परिणामस्वरूप लगभग 1.5 मिलियन पंक्तियां चुनी जा रही हैं। प्रत्येक पंक्ति में डेटा बड़ा नहीं है - शायद प्रति पंक्ति 20 बाइट्स। लेकिन यह अभी भी 30 एमबी डेटा है। प्रत्येक पंक्ति में ग्राहक संख्या होती है, और मुझे प्रत्येक ग्राहक के साथ कुछ करने की आवश्यकता होती है।

SqlConnection conn = new SqlConnection(connString); 
SqlCommand command = new SqlCommand("SELECT ... my select goes here", conn); 
using (conn) 
{ 
    conn.Open(); 
    using (SqlDataReader reader = command.ExecuteReader()) 
    { 
     while(reader.Read()) 
     { 
      ... process the customer number here 
     } 
    } 
} 

तो मैं सिर्फ सभी का चयन करें द्वारा लौटाए गए ग्राहकों से अधिक पुनरावृति:

मेरे कोड की तरह कुछ लग रहा है।

मेरा प्रश्न है, क्या इसका परिणाम डेटाबेस के एकाधिक पढ़ने में आता है, या सिर्फ एक? मुझे लगता है कि नेटवर्क बफर 30 एमबी डेटा रखने के लिए पर्याप्त नहीं हैं, तो .NET क्या करता है? एसक्यूएल का परिणाम SQLDataReader के लिए कहीं भी एक पंक्ति से निकलने के लिए कहीं भी घिरा हुआ है() सूचक को आगे बढ़ाता है? या यह डेटाबेस पर वापस चला जाता है?

कारण मैं पूछ रहा हूं कि कोड के भाग "... यहां ग्राहक संख्या को संसाधित करें" कुछ समय ले सकता है, इसलिए 1.5 मिलियन ग्राहकों के लिए कोड (ऊपर लूप ऊपर) में कई घंटे लगेंगे पूर्ण। हालांकि यह हो रहा है, क्या मुझे डेटाबेस पर मेरे पीछे अवरुद्ध करने वाले अन्य लोगों के बारे में चिंता करने की ज़रूरत है, या क्या मैं इस ज्ञान में सुरक्षित हूं कि मैंने डेटाबेस से अपना एक चयन किया है और मैं फिर से वापस नहीं जा रहा हूं?

+2

[कैसे डेटा रीडर काम करता है] (http://stackoverflow.com/questions/1383920/how-datareader-works) – Steve

+0

तो आपके पास 2-प्रश्न का प्रश्न है? => डेटरेडर कैसे काम करता है और यह मेरी क्वेरी और अन्य उपयोगकर्ताओं को डीबी – Schuere

+0

पर कैसे प्रभावित करेगा, इस तरह की बड़ी मात्राओं से निपटने के दौरान कभी-कभी आपके कोड के तरीके को बदलने के लिए समझदारी होती है। ग्राहकों पर प्रसंस्करण क्या है? क्या किसी भी ग्राहक को लौटने से पहले अन्य मानदंडों का उपयोग करके बाहर रखा जा सकता है? – HeXanon

उत्तर

1

सब से पहले, मैं कर रहा हूँ वाला, इतने पर निम्नलिखित प्रश्न पर रीडायरेक्ट, जिसमें बताया गया है कि कैसे ताले आदि संसाधित कर रहे हैं:

Understanding SQL Server LOCKS on SELECT queries

मेरा पहला सवाल यहाँ है, कितनी बार होगा आप इस सवाल को चला रहे होंगे। यदि यह दैनिक राशि पर है, तो सुनिश्चित करें कि आप ऐसा समय चुनें जहां कम से कम उपयोगकर्ता डेटाबेस पर काम कर रहे हों।

दूसरा सवाल यह है कि, आप डेटा के साथ क्या करने जा रहे हैं? शायद आपको यह ध्यान में रखना चाहिए कि 1 एम + रिकॉर्ड्स को संसाधित करते समय, एक संग्रहित प्रक्रिया तेज होगी क्योंकि यह डेटाबेस पर सब कुछ संसाधित करती है और यातायात को कम रखेगी।

+0

SELECT (NOLOCK) संकेत का उपयोग करता है, और प्रत्येक दिन कम से कम एक बार चलाया जाएगा। तालिका में हमेशा 1.5 मिलियन पंक्तियां नहीं रहेंगी, लेकिन अब वहां है। एक बार प्रक्रिया परिपक्व होने के बाद शायद प्रक्रिया में केवल 20,000-30,000 पंक्तियां होंगी। प्रत्येक ग्राहक की प्रसंस्करण कठिन है, और इसमें अन्य डेटाबेस से पढ़ने (लिखने और लिखने) शामिल हैं। एक संग्रहित प्रक्रिया काम नहीं करेगा। – JeffR

+1

@jeffR, क्या आप चयन करते समय, अद्यतन/अद्यतन सम्मिलित करते समय हैं? – Schuere

+1

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

3

अनुरोध एक बार भेजा गया, हर बार जब आपका पाठक आगे बढ़ता है। फिर परिणाम आकार के आधार पर कई परिणाम सेट द्वारा ग्राहक को वापस भेजा जाएगा।

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

रेफरी http://msdn.microsoft.com/en-us/library/ms187602.aspx

एक अनुरोध के निष्पादन के लिए प्रस्तुत किया जाता है, एसक्यूएल सर्वर परिणाम भेजता निम्नलिखित तरीके से ग्राहकों को वापस सेट:

  1. एसक्यूएल सर्वर से एक नेटवर्क पैकेट प्राप्त करता है क्लाइंट ट्रांजैक्ट-एसक्यूएल कथन या ट्रांजैक्ट-एसक्यूएल कथन का बैच निष्पादित किया गया है।
  2. SQL सर्वर संकलित करता है और कथन या बैच निष्पादित करता है।
  3. एसक्यूएल सर्वर परिणाम सेट की पंक्तियों को डालने शुरू करता है, या नेटवर्क पैकेट में क्लाइंट को भेजकर परिणाम बैच या संग्रहीत प्रक्रिया से परिणाम सेट करता है। एसक्यूएल सर्वर प्रत्येक पैकेट में जितना संभव हो उतना परिणाम पंक्तियों को सेट करता है।
  4. परिणाम सेट पंक्तियों वाले पैकेट को ग्राहक के बफर में कैश किया जाता है। चूंकि क्लाइंट एप्लिकेशन पंक्तियों को लाता है, ओडीबीसी ड्राइवर या ओएलई डीबी प्रदाता पंक्तियों को नेटवर्क बफर से खींचता है और डेटा को क्लाइंट एप्लिकेशन में स्थानांतरित करता है। ग्राहक दिशा में एक समय में परिणामों को एक पंक्ति पुनर्प्राप्त करता है।

एक बड़े ब्लॉक में एक आवेदन के लिए एक डिफ़ॉल्ट परिणाम सेट नहीं दिया गया है। परिणाम सेट क्लाइंट पर नेटवर्क बफर में कैश किया गया है। आवेदन एक समय में एक पंक्ति सेट परिणाम के माध्यम से मिलता है। प्रत्येक fetch पर, ओएलई डीबी प्रदाता या ओडीबीसी चालक नेटवर्क बफर में अगली पंक्ति से डेटा को अनुप्रयोग में चर में ले जाता है। ओएलई डीबी, ओडीबीसी, और एडीओ अनुप्रयोग उन पंक्तियों को पुनः प्राप्त करने के लिए एक ही एपीआई फ़ंक्शंस का उपयोग करते हैं जिनका उपयोग वे कर्सर से पंक्तियों को लाने के लिए करेंगे। SqlClient प्रबंधित प्रदाता डिफ़ॉल्ट परिणाम सेट का पर्दाफाश करने के लिए SqlDataReader क्लास का उपयोग करता है। जब MultiActiveResultSets को सत्य पर सेट किया गया है, तो एक से अधिक SqlDataReader को किसी दिए गए समय पर खोलने की अनुमति है।

रेफरी: http://technet.microsoft.com/en-us/library/ms187602(v=sql.105).aspx

+1

यह बताता है कि नेटवर्क में डेटा कैसे प्रसारित किया जाता है, लेकिन यह मुझे नहीं बताता है कि एक ही लेनदेन में डेटाबेस से सभी डेटा निकाले जाते हैं। सवाल यह है कि, जब चयन निष्पादित किया जाता है, तो क्या यह एक एकल, एकाधिकार लेनदेन के रूप में किया जाता है? यदि ऐसा है, तो यह 30 एमबी डेटा हो सकता है, जो मुझे छोटे टुकड़ों में जबकि (reader.Read()) लूप में खिलाया जाता है। 30 एमबी डेटा कहां रखा जाता है? क्या यह वास्तव में डेटाबेस से पढ़ा जाता है और कहीं भी बफर में संग्रहीत होता है, या जबकि लूप वास्तव में डेटाबेस पर वापस जा रहा है और वहां यातायात पैदा कर रहा है? क्या ExecuteReader() के बाद डेटाबेस के साथ किया गया है? – JeffR

+0

यह स्पष्ट है कि ट्रांजैक्ट एसक्यूएल क्वेरी के लिए केवल एक ही अनुरोध भेजा जाएगा। सर्वर क्वेरी निष्पादित करता है। फिर SQL सर्वर परिणाम नेटवर्क पैकेट में पैक करता है और पूरे परिणाम भेजे जाने तक क्लाइंट को वापस भेजता रहता है। क्लाइंट इसे कैश में संग्रहीत करता है ताकि आपका एप्लिकेशन पंक्ति से पंक्ति को पढ़ सके। इसका मतलब है कि आपके 30 एमबी डेटा सर्वर पर तब तक रखा जा रहा है जब तक कि पूरे परिणाम नहीं भेजे जाते। नेटवर्क पैकेट प्राप्त करने के लिए यातायात होगा, हर बार आपके पाठक के लिए अनुरोध भेजने के लिए नहीं। मैं अपने उत्तर में कुछ अतिरिक्त जानकारी जोड़ूंगा। कृपया इसे जांचें – anbuj

4

का चयन एक "एकल, अखंड लेन-देन" के रूप में क्रियान्वित की जाएगी। आउटपुट का संतुलन SQL सर्वर में कैश किया गया है और नेटवर्क पर बाहर निकला है क्योंकि प्रोटोकॉल निर्धारित करता है कि इसे प्राप्त करने के लिए बफर उपलब्ध है। SQL सर्वर प्रत्येक बार डेटा तालिकाओं में वापस नहीं जाएगा, हालांकि। उस बिंदु पर डेटा की स्थिति उस पर पारित मूल SELECT को आपके आवेदन पर वापस कर दिया जाएगा। यदि आपके पास निर्दिष्ट (NOLOCK) है तो आपके पास डेटा पर कोई और प्रभाव नहीं पड़ेगा। अन्य लोग & पढ़ सकते हैं इसे लिखें; आप उनके परिवर्तन नहीं देखेंगे। आपने एसक्यूएल सर्वर के साथ समाप्त नहीं किया है, हालांकि, आखिरी पंक्ति आपके ऐप सर्वर के बफर में, घंटे बाद तक है। प्रत्येक में नेटवर्क ट्रैफिक होगा "मेरे पास अब और अधिक जगह है, कृपया" लेकिन पूरे 30 एमबी एक बार में सभी के मुकाबले काफी अधिक नहीं है।

बड़े परिणाम सेट और लंबी चलने वाली प्रक्रियाओं के साथ आप बैच में डेटा को संसाधित करने के लिए अपना आवेदन लिखना बेहतर कर सकते हैं, भले ही आधारभूत संरचना पूर्ण क्वेरी आउटपुट का समर्थन कर सके। प्रत्येक बैच की गई क्वेरी का उत्तर देने में कम संसाधन लगते हैं। विफलता के मामले में आपको केवल शेष पंक्तियों को संसाधित करने की आवश्यकता है; आपको शुरुआत से फिर से शुरू करने की ज़रूरत नहीं है। आपका आवेदन कुल मिलाकर अधिक काम कर देगा, लेकिन प्रत्येक खंड पर्यावरण के लिए कम विघटनकारी होगा।

+0

'(NOLOCK) 'को छोड़कर' SELECT' ताले रखने के कारण होगा? क्या SQL सर्वर वास्तव में आउटपुट को आंतरिक रूप से एक अस्थायी तालिका में स्पूल करेगा यदि परिणाम सेट पर्याप्त बड़ा है? – binki

+1

@binki आम तौर पर, NOLOCK को छोड़कर ताले लेनदेन के अंत तक ताले बनाएंगे। लेनदेन के [अलगाव स्तर] (https://docs.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql) से अवगत रहें, हालांकि। –

+0

@binki ऑप्टिमाइज़र चयनित योजना के हिस्से के रूप में TempDB पर स्पूल करना चुन सकता है। मुझे विश्वास नहीं है कि यह एक व्यस्त नेटवर्क बफर के परिणामस्वरूप ऐसा करेगा, लेकिन (लेकिन कोई सबूत नहीं है)। –

संबंधित मुद्दे