2009-02-12 17 views
6

वर्तमान में से मैं ने programmation (ग #) उत्पन्न क्वेरी के इस प्रकारमें डालने सुधार - चयन, एसक्यूएल क्वेरी

INSERT INTO TableName (Field1, Field2, Field3) 
SELECT Field1, Field2, Field3 FROM TableName2 

समस्या का चयन कई रिकॉर्ड का एक परिणाम हो सकता है वह यह है कि मिल गया है (जैसे एक लाख) , इसलिए यह कई बार लगता है और परिणाम एक कनेक्शन टाइमआउट है।

इसके अलावा, अगर मैं एक डालने में में सभी डालने अलग (इस उदाहरण के लिए, एक लाख डालने प्रश्नों), यह बहुत लंबे समय निष्पादित करने के लिए ... लेकिन यह काम लेना है ...

वहाँ एक है जिस तरह से मैं इस प्रकार की क्वेरी में सुधार कर सकता हूं?

मैं उपयोग MSSQL 2005

Thx

उत्तर

8

मुझे पता चला है कि आपने सम्मिलित बयान है कि अनुक्रम में क्रियान्वित कर रहे हैं की एक बहुत कुछ है, तो आप डालने कथनों में से प्रत्येक xxxx संख्या के बाद एक 'गो' बयान जोड़कर प्रदर्शन में सुधार कर सकते हैं कि,:

... 
INSERT INTO Table (...) VALUES (...) 
INSERT INTO Table (...) VALUES (...) 
INSERT INTO Table (...) VALUES (...) 
GO 
INSERT INTO Table (...) VALUES (...) 
INSERT INTO Table (...) VALUES (...) 
... 

एक और संभावना है हो सकता है, यह सुनिश्चित करें कि में अपने सम्मिलित करें .. क्वेरी से किसी एक को चुनें समय में सब कुछ सम्मिलित नहीं करता है, बजाय पेजिंग तकनीक किसी तरह का उपयोग करने के लिए है:

INSERT INTO Table ... 
SELECT ... 
FROM OtherTable WHERE Id > x and Id < y 
6

ठीक है, अगर यह एक पूरी कॉपी है, मुझे आश्चर्य है कि अगर आप थोक लोड उपकरणों पर गौर नहीं करना चाहिए?

  • बल्क सम्मिलित करें (TSQL)
  • SqlBulkCopy (.NET)
  • BCP (कमांड लाइन)
  • आदि

आप था एक Where खंड, मैं जाँच चाहते हैं तो कि यह उचित रूप से अनुक्रमित किया गया था ...

अतिरिक्त:

  • शायद अनुक्रमणिका ड्रॉप और सम्मिलित करने से पहले से चलाता है (बाद में पुन: बनाने)
  • पूरे मेज छोड़ने और चयन जांच का उपयोग कर विचार? (टिप्पणियों को देखने के)
+0

इसमें चयन न करें ... यह क्वेरी समाप्त होने तक सिस्टम टेबल लॉक कर देगा क्योंकि तालिका उसी लेनदेन में बनाई जा रही है। यह वैसे भी कोई प्रदर्शन लाभ नेट होगा। –

+0

@ ब्रायन - पर्याप्त मेला; -पी –

2

एक समझदार मूल्य के SqlCommand आप उपयोग कर रहे CommandTimeout प्रॉपर्टी सेट (10 मिनट या कुछ और)। याद रखें कि CommandTimeout सेकंड में है।

0

आप क्या समस्या का संकेत नहीं है अपने इस दृष्टिकोण के साथ हल करना। स्पष्ट रूप से एक रिकॉर्ड रिकॉर्ड को संकीर्ण करेगा। लेकिन यदि परिणाम सेट को नई तालिका में संशोधित नहीं किया जा रहा है, तो डेटा को दोहराना क्यों है? स्रोत से सीधे सवाल क्यों नहीं?

0

या तो एक फ़ाइल और फिर BCP/बल्क सम्मिलित करें या इसे बैच अप 5K के बैच में या तो

0

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

+0

सी # से एसकब्लूल्ककॉपी ठीक है ... –

+0

और, वह डेटाबेस का उपयोग कर रहा है। सी # कोड सिर्फ क्वेरी को बंद कर देता है। –

0

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

मूल रूप से आप जो करना चाहते हैं वह टैबलेटनाम में एक डालने है (...) तालिका नाम से चुनें (...) जहां प्राथमिक कुंजी (प्रक्षेपित करने योग्य शीर्ष 10000 कुंजी का चयन करें)

शीर्ष 10000 जो आप माध्यमिक परिणाम सेट में चाहते हैं, ताकि आप उन्हें temp तालिका से निकाल सकें ताकि उन्हें फिर से संसाधित न किया जा सके।

फिर भी एक और तरीका कर्सर का उपयोग एक समय में आपके द्वारा संसाधित रिकॉर्ड्स की संख्या को कम करने के लिए करना होगा।

एक और लूप विधि थोड़ी देर में ऐसा कुछ करने के लिए होगी।

पूर्णांक (TableName से चयन गणना (PrimaryKey) जहां PrimaryKey नहीं destinstiontable में) सेट @stop =

जबकि (@stop> 0) लेनदेन

डालने destinationTable में शुरू (के रूप में @stop घोषित ...) चयन (...) sourcetable जहां PrimaryKey में नहीं (destinationtable से PrimaryKey चुनें) से

प्रतिबद्ध

सेट @stop = (चुनिंदा गणना (PrimaryKey) TableName से जहां PrimaryKey नहीं destinstiontable में) अंत

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

कुछ कहा गया है कि शायद आपकी सबसे अच्छी शर्त है। बीसीपी, डीटीएस, या कुछ अन्य थोक उपकरण का प्रयोग करें। यदि आप इंडेक्स को छोड़ सकते हैं, तो यह चीजें बहुत तेज हो जाएगी।

+0

अकेले चाबियों के साथ अस्थायी तालिका बनाना tempdb पेग करेगा और केवल आईओ मुद्दों को और खराब कर देगा। –

+0

सच है कि यह करता है। मैं अभी भी इस स्थिति में डीटीएस या कुछ अन्य बीसीपी उपकरण का उपयोग करना चाहता हूं। इसे मैन्युअल रूप से करने की कोशिश कर सिर्फ दर्दनाक और संसाधन गहन हो सकता है। –

1

यहां कुछ अच्छे जवाब दिए गए हैं।

बस यह जोड़ना पसंद है कि यदि आपके पास गंतव्य तालिका पर अनुक्रमणिका है तो वे ऑपरेशन को धीमा कर देंगे। हालांकि, अगर आप बूंद बनाने की तकनीक करते हैं तो इंडेक्स का पुनर्निर्माण कभी-कभी लंबा समय ले सकता है।

आप अनुक्रमणिका ड्रॉप नहीं करना चाहते हैं, तो आपके SELECT कि गंतव्य क्लस्टर सूचकांक मैचों में एक ORDER BY उपयोग करते हैं, यह मदद करने के लिए लगता है (शायद पेज विभाजन को कम मदद करता है)।

3

ठीक है, कुछ मौलिक मुद्दे हैं।

  1. मैं \ हे - एक और मेज से पढ़ते समय एक तालिका में सम्मिलित करना होगा सबसे संभावित कारण डिस्क विवाद करता है, तो टेबल अलग डिस्क पर नहीं हैं।विरोधी टेबल को शारीरिक रूप से अलग स्पिंडल पर रखें।

  2. लेनदेन लॉग - आपको यह सुनिश्चित करने की आवश्यकता है कि आपका लेनदेन लॉग अपनी डिस्क पर है, या छोटे लेनदेन में काम करता है (एक समय में कुछ हज़ार पंक्तियां) या बीसीपी \ थोक सम्मिलित करें जो लॉग नहीं है।

  3. क्लस्टर अनुक्रमित - आप एक लक्ष्य तालिका में इन पंक्तियों के सभी डालने कर रहे हैं, और यह सूचकांक क्लस्टर है (भौतिक आदेश डेटा डिस्क के लिए लिखा है) क्रमिक रूप से लेखन नहीं है, तो डिस्क आईओ आवश्यकताओं की वजह से छत के माध्यम से जाना पेज विभाजन और पुनः आवंटन। एक अनुक्रमिक बीज वाली कुंजी प्राप्तकर्ता तालिका पर क्लस्टर्ड इंडेक्स बनाने के लिए एक आसान फिक्स हो सकता है। यह आमतौर पर सुनिश्चित करेगा कि आपको तालिका में अनुक्रमिक लिखना होगा और लगभग हमेशा अंत में।

  4. फ़ाइल विस्तार - सुनिश्चित करें कि आपके पास इसकी फ़ाइलों को एक सभ्य दर पर विस्तारित करने के लिए SQL सेट है, जैसे 10% या उससे भी अधिक। अन्यथा इसे लगातार अपनी फाइलों का आकार बदलना होगा और डिस्क को शून्य करना होगा। एसक्यूएल सेवा उपयोगकर्ता के लिए आपकी समूह नीतियों में थोक फ़ाइल ऑपरेशन अनुमति को सक्षम करने जैसी डिस्क को शून्य से बाहर करने से रोकने के तरीके भी हैं।

काफी स्पष्ट रूप से, और कहा कि अन्य की तुलना में दूसरों सुझावों में से कुछ है, यह आप वास्तव में तेजी से हो एक सौदे में पंक्तियों के लाखों लोगों के साथ एक डालने कर देगा अत्यधिक संभावना नहीं है। यदि आपने थोक सम्मिलन के माध्यम से ऐसा किया है, तो यह बहुत तेजी से होगा, हालांकि यह एक अनुप्रयोग परिप्रेक्ष्य से आपको जो चाहिए वह नहीं हो सकता है।

0

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

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