मुझे SQL सर्वर के BULK INSERT
कमांड का उपयोग करके कुछ पुराने कोड को फिर से लिखना होगा क्योंकि स्कीमा बदल गया है, और यह मेरे लिए हुआ है कि शायद मुझे स्विचिंग के बारे में सोचना चाहिए इसके बजाए एक टीवीपी के साथ संग्रहीत प्रक्रिया में, लेकिन मुझे आश्चर्य है कि प्रदर्शन पर इसका क्या प्रभाव हो सकता है।बीसीपी/बल्क इंसर्ट बनाम तालिका-मूल्यवान पैरामीटर्स का प्रदर्शन
कुछ पृष्ठभूमि जानकारी है कि समझाने मदद कर सकता है कारण है कि मैं इस सवाल पूछ रहा हूँ:
डेटा वास्तव में एक वेब सेवा के माध्यम से में आता है। वेब सेवा डेटाबेस सर्वर पर एक साझा फ़ोल्डर में एक टेक्स्ट फ़ाइल लिखती है जो बदले में
BULK INSERT
निष्पादित करती है। यह प्रक्रिया मूल रूप से SQL Server 2000 पर कार्यान्वित की गई थी, और उस समय सर्वर पर कुछ सौINSERT
कथनों को चकित करने के अलावा वास्तव में कोई विकल्प नहीं था, जो वास्तव में मूल प्रक्रिया थी और एक प्रदर्शन आपदा थी।डेटा को स्थायी स्टेजिंग तालिका में थोक डाला जाता है और फिर एक बड़ी तालिका में विलय किया जाता है (जिसके बाद इसे स्टेजिंग तालिका से हटा दिया जाता है)।
डालने के लिए डेटा की मात्रा "बड़ी" है, लेकिन "विशाल" नहीं - आमतौर पर कुछ सौ पंक्तियां, शायद दुर्लभ उदाहरणों में 5-10k पंक्तियां शीर्ष पर होती हैं। इसलिए मेरा आंत महसूस यह है कि
BULK INSERT
गैर-लॉग इन ऑपरेशन होने से नहीं होगा बड़ा अंतर (लेकिन निश्चित रूप से मुझे यकीन नहीं है, इसलिए सवाल)।सम्मिलन वास्तव में एक बहुत बड़ी पाइपलाइन वाली बैच प्रक्रिया का हिस्सा है और उत्तराधिकार में कई बार होने की आवश्यकता है; इसलिए प्रदर्शन महत्वपूर्ण है।
कारणों मैं एक TVP साथ BULK INSERT
को प्रतिस्थापित करना चाहते हैं:
NetBIOS से अधिक पाठ फ़ाइल लेखन शायद पहले से ही कुछ समय की लागत है, और यह एक वास्तुशिल्प के नजरिए से बहुत भीषण है।
मेरा मानना है कि स्टेजिंग तालिका समाप्त हो सकती है (और चाहिए)। इसका मुख्य कारण यह है कि सम्मिलित डेटा को सम्मिलन के एक ही समय में कुछ अन्य अपडेटों के लिए उपयोग करने की आवश्यकता है, और यह लगभग-खाली स्टेजिंग का उपयोग करने के बजाय बड़े उत्पादन तालिका से अद्यतन का प्रयास करने के लिए बहुत महंगा है तालिका। एक टीवीपी के साथ, पैरामीटर मूल रूप से स्टेजिंग टेबल है, मैं मुख्य डालने से पहले/बाद में कुछ भी कर सकता हूं।
मैं डुप्ली-चेकिंग, क्लीनअप कोड और थोक आवेषण से जुड़े सभी ओवरहेड से काफी कुछ कर सकता हूं।
स्टेजिंग टेबल या tempdb पर लॉक विवाद के बारे में चिंता करने की आवश्यकता नहीं है यदि सर्वर को इनमें से कुछ लेनदेन एक बार में मिलते हैं (हम इसे टालने का प्रयास करते हैं, लेकिन ऐसा होता है)।
मैं स्पष्ट रूप से उत्पादन में कुछ भी डालने से पहले इस प्रोफाइल लिए जा रहा हूँ, लेकिन मैंने सोचा कि यह एक अच्छा विचार पहले चारों ओर इससे पहले कि मैं यह सब समय खर्च करते हैं पूछने के लिए हो सकता है, अगर किसी को भी जारी करने के लिए किसी भी कड़ी चेतावनी है, यह देखने इस उद्देश्य के लिए टीवीपी का उपयोग करने के बारे में।
तो - किसी भी व्यक्ति के लिए जो SQL Server 2008 के साथ पर्याप्त आरामदायक है या कम से कम इसकी जांच करने के लिए, निर्णय क्या है?आवेषण के लिए, मान लीजिए, कुछ सौ से कुछ हज़ार पंक्तियां, जो लगातार आधार पर होती हैं, क्या टीवीपी सरसों काटते हैं? थोक आवेषण की तुलना में प्रदर्शन में कोई महत्वपूर्ण अंतर है?
अद्यतन: अब 9 2% कम प्रश्न चिह्न के साथ!
(उर्फ: परीक्षण के परिणाम)
अंतिम परिणाम क्या एक 36-चरण तैनाती प्रक्रिया की तरह लगता है के बाद उत्पादन में है। दोनों समाधानों का व्यापक परीक्षण किया गया:
- साझा फ़ोल्डर कोड को बाहर निकालना और सीधे
SqlBulkCopy
कक्षा का उपयोग करना; - टीवीपी के साथ एक संग्रहीत प्रक्रिया में स्विचिंग।
बस इतना पाठकों की एक विचार क्या वास्तव में परीक्षण किया गया था प्राप्त कर सकते हैं, इस डेटा की विश्वसनीयता के बारे में कोई संदेह दूर करने के लिए, यहाँ क्या इस आयात प्रक्रिया वास्तव में करता है की एक अधिक विस्तृत विवरण है:
सामान्य रूप से लगभग 20-50 डेटा पॉइंट्स (हालांकि यह कभी-कभी कुछ सौ हो सकता है) के साथ एक अस्थायी डेटा अनुक्रम के साथ प्रारंभ करें;
उस पर पागल प्रसंस्करण का पूरा समूह करें जो ज्यादातर डेटाबेस से स्वतंत्र है। यह प्रक्रिया समानांतर है, इसलिए (1) में अनुक्रमों के लगभग 8-10 एक ही समय में संसाधित किए जा रहे हैं। प्रत्येक समांतर प्रक्रिया 3 अतिरिक्त अनुक्रम उत्पन्न करती है।
सभी 3 अनुक्रमों और मूल अनुक्रम लें और उन्हें एक बैच में गठबंधन करें।
सभी 8-10 अब-समाप्त प्रोसेसिंग कार्यों से बैच को एक बड़े सुपर-बैच में मिलाएं।
BULK INSERT
रणनीति (अगले चरण देखें), या टीवीपी रणनीति (चरण 8 पर छोड़ें) का उपयोग करके इसे आयात करें।पूरे सुपर-बैच को 4 स्थायी स्टेजिंग टेबल में डंप करने के लिए
SqlBulkCopy
कक्षा का उपयोग करें।चलाया जाने वाला एक संग्रहीत प्रक्रिया है कि (क) तालिकाओं के 2, कई
JOIN
की स्थिति, और सहित तो पर एकत्रीकरण कदम की एक गुच्छा करता है (ख) दोनों एकत्रित और गैर एकत्रित का उपयोग कर एकMERGE
6 पर उत्पादन टेबल करता है डेटा। (समाप्त)या
उत्पन्न डेटा वाली 4
DataTable
वस्तुओं मर्ज करने; उनमें से 3 में सीएलआर प्रकार होते हैं जो दुर्भाग्यवश एडीओ.NET टीवीपी द्वारा समर्थित नहीं होते हैं, इसलिए उन्हें स्ट्रिंग प्रस्तुतियों के रूप में स्थानांतरित किया जाना चाहिए, जो प्रदर्शन को थोड़ा सा नुकसान पहुंचाते हैं।टीवीएस को एक संग्रहीत प्रक्रिया में फ़ीड करें, जो अनिवार्य रूप से उसी प्रसंस्करण (7) के रूप में कार्य करता है, लेकिन सीधे प्राप्त तालिकाओं के साथ।(समाप्त)
परिणाम यथोचित करीब थे, लेकिन TVP दृष्टिकोण अंततः औसतन बेहतर प्रदर्शन किया, तब भी जब डेटा एक छोटी राशि से 1000 पंक्तियाँ पार हो गई।
ध्यान दें कि यह आयात प्रक्रिया उत्तराधिकार में कई बार कई बार चलती है, इसलिए यह गणना करके औसत समय प्राप्त करना बहुत आसान था कि यह सभी विलयों को समाप्त करने के लिए कितने घंटे (हाँ, घंटे) लगा।
मूल रूप से, औसत विलय को पूरा करने के लिए लगभग 8 सेकंड लगते थे (सामान्य लोड के तहत)। नेटबीओएसएस क्लोज को हटाने और SqlBulkCopy
पर स्विच करने से समय लगभग 7 सेकंड तक कम हो गया। टीवीपी पर स्विच करने से समय 5.2 सेकंड प्रति बैच में कम हो गया। यह एक 35% सुधार एक प्रक्रिया के लिए थ्रूपुट में है जिसका चलने का समय घंटों में मापा जाता है - इसलिए बिल्कुल बुरा नहीं। यह SqlBulkCopy
पर ~ 25% सुधार भी है।
मुझे वास्तव में काफी विश्वास है कि वास्तविक सुधार इस से काफी अधिक था। परीक्षण के दौरान यह स्पष्ट हो गया कि अंतिम विलय अब महत्वपूर्ण मार्ग नहीं था; इसके बजाए, वेब सेवा जो सभी डेटा प्रोसेसिंग कर रही थी, आने वाले अनुरोधों की संख्या के तहत बकल शुरू हो रही थी। न तो सीपीयू और न ही डेटाबेस I/O वास्तव में अधिकतम हो गया था, और कोई महत्वपूर्ण लॉकिंग गतिविधि नहीं थी। कुछ मामलों में हम लगातार विलय के बीच कुछ निष्क्रिय सेकंड का अंतर देख रहे थे। SqlBulkCopy
का उपयोग करते समय थोड़ा सा अंतर था, लेकिन बहुत छोटा (आधे सेकेंड या तो)। लेकिन मुझे लगता है कि एक और दिन के लिए एक कहानी बन जाएगी।
निष्कर्ष: तालिका-मूल्यवान पैरामीटर वास्तव में जटिल आकार के लिए BULK INSERT
संचालन से बेहतर प्रदर्शन करते हैं + मध्यम आकार के डेटा सेट पर चल रही प्रक्रियाओं को परिवर्तित करें।
मैं, एक अन्य बिंदु जोड़ने सिर्फ लोग समर्थक मचान-टेबल रहे हैं की ओर से किसी भी आशंका शांत करने करना चाहते हैं। एक तरह से, यह पूरी सेवा एक विशाल स्टेजिंग प्रक्रिया है। प्रक्रिया के प्रत्येक चरण पर अत्यधिक लेखापरीक्षा की जाती है, इसलिए को की आवश्यकता नहीं है यह निर्धारित करने के लिए कि कोई विशेष विलय विफल क्यों हुआ (हालांकि व्यवहार में यह लगभग कभी नहीं होता)। हमें बस इतना करना है कि सेवा में डीबग फ्लैग सेट करें और यह डीबगर को तोड़ देगा या डाटाबेस की बजाय फाइल को डंप करेगा।
दूसरे शब्दों में, हमारे पास पहले से ही प्रक्रिया में पर्याप्त अंतर्दृष्टि है और स्टेजिंग टेबल की सुरक्षा की आवश्यकता नहीं है; पहली जगह में स्टेजिंग टेबल रखने का एकमात्र कारण यह था कि INSERT
और UPDATE
बयानों पर थ्रैशिंग से बचने के लिए हमें अन्यथा उपयोग करना होगा। मूल प्रक्रिया में, स्टेजिंग डेटा केवल एक दूसरे के अंशों के लिए स्टेजिंग तालिका में रहता था, इसलिए इसमें रखरखाव/रखरखाव शर्तों में कोई मूल्य नहीं जोड़ा गया।
यह भी ध्यान दें कि हमारे पास टीवीपी के साथ प्रत्येक एकल BULK INSERT
ऑपरेशन को प्रतिस्थापित नहीं किया गया है। कई परिचालन जो डेटा की बड़ी मात्रा से निपटते हैं और/या डीबी में फेंकने के अलावा अन्य डेटा के साथ कुछ विशेष करने की आवश्यकता नहीं है, फिर भी SqlBulkCopy
का उपयोग करें। मैं यह सुझाव नहीं दे रहा हूं कि टीवीपी एक प्रदर्शन पैनसिया हैं, केवल वे इस विशिष्ट उदाहरण में SqlBulkCopy
से अधिक सफल हुए हैं जिसमें प्रारंभिक स्टेजिंग और अंतिम विलय के बीच कई परिवर्तन शामिल हैं।
तो आपके पास यह है। सबसे प्रासंगिक लिंक खोजने के लिए प्वाइंट टीटीनी जाता है, लेकिन मैं अन्य प्रतिक्रियाओं की भी सराहना करता हूं। एक बार फिर धन्यवाद!
लिंक के लिए धन्यवाद, यह वास्तव में काफी उपयोगी है क्योंकि एमएस टीवीपी की सिफारिश करता है जब डेटा जटिल तर्क (जो करता है) खिलाता है और हमारे पास बैच आकार को डायल या डाउन करने की क्षमता भी है, इसलिए हम बहुत दूर नहीं जाते हैं 1k-पंक्ति दर्द बिंदु। इस पर आधारित, कम से कम कोशिश करने और देखने के लिए समय हो सकता है, भले ही यह बहुत धीमी हो। – Aaronaught
हाँ लिंक दिलचस्प है।@Aaronaught - इस तरह की स्थितियों में, संभावित दृष्टिकोणों के प्रदर्शन की खोज और विश्लेषण करने के लिए हमेशा अच्छा होता है, इसलिए मुझे आपके निष्कर्ष सुनना होगा! – AdaTheDev