जहाँ तक मैं बता सकता हूँ कि आप एक बहुत ही समान तरीके से एक बल्क इंसर्ट को ऑप्टिमाइज़ कर सकते हैं जो आप एक रेगुलर इंसर्ट को ऑप्टिमाइज़ करेंगे। आमतौर पर, एक साधारण डालने के लिए एक क्वेरी योजना बहुत जानकारीपूर्ण नहीं होती है ताकि योजना न होने के बारे में चिंता न करें। मैं सम्मिलित करने के अनुकूलन के कुछ तरीकों पर जाऊंगा, लेकिन उनमें से अधिकांश संभवत: आपके द्वारा निर्दिष्ट प्रश्न के लिए लागू नहीं होंगे। हालांकि, वे मददगार हो सकते हैं यदि भविष्य में आपको बड़ी मात्रा में डेटा लोड करने की आवश्यकता होती है।
1. क्लस्टरिंग ऑर्डर में डेटा डालें
SQL सर्वर अक्सर तालिका में एक क्लस्टर इंडेक्स के साथ डालने से पहले डेटा को सॉर्ट करेगा। कुछ तालिकाओं और अनुप्रयोगों के लिए आप फ्लैट फ़ाइल में डेटा को सॉर्ट करके प्रदर्शन को बेहतर बना सकते हैं और SQL सर्वर को बता सकते हैं कि डेटा को ORDER
तर्क के माध्यम से क्रमबद्ध किया गया है BULK INSERT
:
आदेश ({कॉलम [ASC | DESC]} [, ... n])
निर्दिष्ट करता है कि डेटा फ़ाइल में डेटा कैसे सॉर्ट किया गया है। यदि आयात किए जा रहे डेटा को टेबल पर क्लस्टर किए गए इंडेक्स के अनुसार क्रमबद्ध किया जाता है, तो थोक आयात प्रदर्शन में सुधार होता है।
चूँकि आप एक IDENTITY
स्तंभ को संकुल कुंजी के रूप में उपयोग कर रहे हैं, इसलिए आपको इस बारे में चिंता करने की आवश्यकता नहीं है।
2. TABLOCK
यदि संभव हो तो उपयोग करें
यदि आपको अपनी तालिका में केवल एक सत्र डेटा डालने की गारंटी दी जाती है, तो आप इसके लिए TABLOCK
तर्क निर्दिष्ट कर सकते हैं BULK INSERT
। यह लॉक विवाद को कम कर सकता है और कुछ परिदृश्यों में न्यूनतम लॉगिंग को जन्म दे सकता है। हालाँकि, आप एक तालिका में एक सम्मिलित सूचकांक के साथ सम्मिलित कर रहे हैं जिसमें पहले से ही डेटा शामिल है ताकि आपको ट्रेस ध्वज 610 के बिना न्यूनतम लॉगिंग न मिले जो बाद में इस उत्तर में उल्लिखित है।
यदि TABLOCK
संभव नहीं है, क्योंकि आप कोड नहीं बदल सकते हैं , तो सभी आशा खो नहीं है। उपयोग करने पर विचार करें sp_table_option
:
EXEC [sys].[sp_tableoption]
@TableNamePattern = N'dbo.BulkLoadTable' ,
@OptionName = 'table lock on bulk load' ,
@OptionValue = 'ON'
एक अन्य विकल्प ट्रेस फ्लैग 715 को सक्षम करना है ।
3. एक उपयुक्त बैच आकार का उपयोग करें
कभी-कभी आप बैच आकार को बदलकर आवेषण को ट्यून करने में सक्षम होंगे।
ROWS_PER_BATCH = row_per_batch
डेटा फ़ाइल में डेटा की पंक्तियों की अनुमानित संख्या को इंगित करता है।
डिफ़ॉल्ट रूप से, डेटा फ़ाइल का सारा डेटा सर्वर को एकल लेनदेन के रूप में भेजा जाता है, और बैच में पंक्तियों की संख्या क्वेरी ऑप्टिमाइज़र के लिए अज्ञात है। यदि आप ROWS_PER_BATCH (एक मान> 0 के साथ) निर्दिष्ट करते हैं, तो सर्वर इस मान का उपयोग बल्क-आयात ऑपरेशन को अनुकूलित करने के लिए करता है। ROWS_PER_BATCH के लिए निर्दिष्ट मान लगभग पंक्तियों की वास्तविक संख्या के समान होना चाहिए। प्रदर्शन के विचारों के बारे में जानकारी के लिए, इस विषय में बाद में "रिमार्क्स" देखें।
यहाँ लेख में बाद में बोली है:
यदि किसी एकल बैच में फ्लश किए जाने वाले पृष्ठों की संख्या एक आंतरिक सीमा से अधिक हो जाती है, तो बैच के शुरू होने पर कौन से पृष्ठों को फ्लश करना है, इसकी पहचान करने के लिए बफर पूल की एक पूरी स्कैन हो सकती है। यह पूर्ण स्कैन थोक-आयात प्रदर्शन को चोट पहुंचा सकता है। आंतरिक सीमा से अधिक होने का एक संभावित मामला तब होता है जब एक बड़े बफर पूल को धीमे I / O सबसिस्टम के साथ जोड़ा जाता है। बड़ी मशीनों पर बफर ओवरफ्लो से बचने के लिए, या तो टैब्लॉक हिंट (जो कि बल्क ऑप्टिमाइजेशन को हटा देगा) का उपयोग न करें या छोटे बैच साइज (जो बल्क ऑप्टिमाइजेशन को संरक्षित करता है) का उपयोग करें।
क्योंकि कंप्यूटर भिन्न होते हैं, हम अनुशंसा करते हैं कि आप अपने डेटा लोड के साथ विभिन्न बैच आकारों का परीक्षण करें ताकि यह पता लगाया जा सके कि आपके लिए सबसे अच्छा क्या है।
व्यक्तिगत रूप से मैं सिर्फ एक ही बैच में सभी 695 पंक्तियाँ सम्मिलित करूंगा। हालांकि बहुत सारे डेटा सम्मिलित करते समय बैच आकार को ट्यूनिंग करना एक बड़ा अंतर बना सकता है।
4. सुनिश्चित करें कि आपको IDENTITY
कॉलम की आवश्यकता है
मुझे आपके डेटा मॉडल या आवश्यकताओं के बारे में कुछ भी पता नहीं है, लेकिन IDENTITY
हर तालिका में एक कॉलम जोड़ने के जाल में मत पड़ो । हारून बर्ट्रेंड ने इस लेख के बारे में कहा है कि बुरी आदतों को किक करने के लिए: प्रत्येक तालिका पर एक पहचान पत्र कॉलम डालना । स्पष्ट होने के लिए, मैं यह नहीं कह रहा हूं कि आपको IDENTITY
इस तालिका से कॉलम को हटा देना चाहिए । हालांकि, यदि आप यह निर्धारित करते हैं कि IDENTITY
कॉलम आवश्यक नहीं है और इसे हटा दें जो सम्मिलित प्रदर्शन में सुधार कर सकता है।
5. अनुक्रमणिका या बाधाओं को अक्षम करें
यदि आपके पास पहले से मौजूद डेटा की तुलना में बड़ी मात्रा में डेटा तालिका में लोड हो रहा है, तो लोड से पहले अनुक्रमित या बाधाओं को अक्षम करने और लोड के बाद उन्हें सक्षम करने के लिए तेज़ हो सकता है। बड़ी मात्रा में डेटा के लिए यह आमतौर पर SQL सर्वर के लिए एक इंडेक्स बनाने के लिए अधिक अक्षम होता है, बजाय इसके कि डेटा टेबल में लोड हो। ऐसा लगता है कि आपने 11500 पंक्तियों के साथ एक तालिका में 695 पंक्तियां डालीं, इसलिए मैं इस तकनीक की सिफारिश नहीं करूंगा।
6. टीएफ 610 पर विचार करें
ट्रेस फ्लैग 610 कुछ अतिरिक्त परिदृश्यों में न्यूनतम लॉगिंग की अनुमति देता है। एक IDENTITY
संकुल कुंजी के साथ अपनी तालिका के लिए , आपको किसी भी नए डेटा पृष्ठों के लिए न्यूनतम लॉगिंग तब तक प्राप्त होगी जब तक कि आपका पुनर्प्राप्ति मॉडल सरल या बल्क-लॉग न हो। मेरा मानना है कि यह सुविधा डिफ़ॉल्ट रूप से नहीं है क्योंकि यह कुछ प्रणालियों पर प्रदर्शन को नीचा दिखा सकता है। इस ट्रेस ध्वज को सक्षम करने से पहले आपको सावधानीपूर्वक परीक्षण करने की आवश्यकता होगी। अनुशंसित Microsoft संदर्भ अभी भी डेटा लोड हो रहा है प्रदर्शन मार्गदर्शिका प्रतीत होता है
आई / ओ मिनिमल लॉगिंग अंडर ट्रेस फ्लैग 610
जब आप एक बल्क लोड लेनदेन करते हैं जो न्यूनतम रूप से लॉग इन किया गया था, तो लोड किए गए सभी पेजों को डिस्क पूर्ण होने से पहले डिस्क में फ्लश किया जाना चाहिए। पहले से मौजूद चेकपॉइंट ऑपरेशन द्वारा पकड़े गए किसी भी फ्लश किए गए पृष्ठ यादृच्छिक I / O का एक बड़ा सौदा बना सकते हैं। इसे पूरी तरह से लॉग ऑपरेशन के साथ विरोधाभास करें, जो लॉग ऑन लिखने के बजाय अनुक्रमिक I / O बनाता है और लोड किए गए पृष्ठों को प्रतिबद्ध समय पर डिस्क में फ्लश करने की आवश्यकता नहीं होती है।
यदि आपका लोड परिदृश्य छोटे पेड़ों पर डाला गया ऑपरेशन है जो चेकपॉइंट सीमाओं को पार नहीं करता है, और आपके पास धीमी आई / ओ प्रणाली है, तो न्यूनतम लॉगिंग का उपयोग वास्तव में सम्मिलित गति को धीमा कर सकता है।
जहां तक मैं बता सकता हूं कि इसका पता लगाने वाले झंडे 610 के साथ कुछ भी नहीं है, बल्कि न्यूनतम लॉगिंग के साथ ही है। मेरा मानना है कि ROWS_PER_BATCH
ट्यूनिंग के बारे में पहले वाला उद्धरण इसी अवधारणा पर हो रहा था।
अंत में, शायद इतना नहीं है कि आप अपनी धुन बना सकें BULK INSERT
। मुझे आपके द्वारा सम्मिलित किए जाने के साथ पढ़ने वाली गणना के बारे में चिंता नहीं होगी। SQL सर्वर रिपोर्ट दर्ज करेगा जब भी आप डेटा डालेंगे। निम्नलिखित बहुत सरल पर विचार करें INSERT
:
DROP TABLE IF EXISTS X_TABLE;
CREATE TABLE X_TABLE (
VAL VARCHAR(1000) NOT NULL
);
SET STATISTICS IO, TIME ON;
INSERT INTO X_TABLE WITH (TABLOCK)
SELECT REPLICATE('Z', 1000)
FROM dbo.GetNums(10000); -- generate 10000 rows
इससे आउटपुट SET STATISTICS IO, TIME ON
:
तालिका 'X_TABLE'। स्कैन संख्या 0, तार्किक 11428 पढ़ता है
मेरे पास 11428 रिपोर्ट पढ़ी गई हैं, लेकिन यह कार्रवाई योग्य जानकारी नहीं है। कभी-कभी रिपोर्ट किए गए रीड्स की संख्या न्यूनतम लॉगिंग द्वारा कम की जा सकती है, लेकिन निश्चित रूप से अंतर को प्रदर्शन लाभ में सीधे अनुवाद नहीं किया जा सकता है।