2013-02-09 26 views
6

माइग्रेशन प्रोजेक्ट के दौरान, मुझे हमारे SQL सर्वर में 4 मिलियन रिकॉर्ड अपडेट का सामना करना पड़ रहा है।रिकॉर्ड-आईडी की सूची का उपयोग कर SQL सर्वर में 4 मिलियन रिकॉर्ड्स अपडेट कर रहा है इनपुट

अद्यतन बहुत आसान है; एक बूलियन क्षेत्र के लिए सही/1 निर्धारित करने की आवश्यकता है और इनपुट मैं सब आईडी के जिसके लिए इस क्षेत्र को भरा जाना चाहिए की एक सूची है। (प्रति पंक्ति एक आईडी)

मैं बिल्कुल एक विशेषज्ञ जब यह नहीं कर रहा हूँ इस आकार के एसक्यूएल कार्यों के लिए आता है, इसलिए मैंने एक "WHERE xxx IN ({list of ids, separated by comma})" युक्त 1 अद्यतन विवरण का प्रयास करना शुरू कर दिया। सबसे पहले, मैंने इसे दस लाख रिकॉर्ड के साथ करने की कोशिश की। परीक्षण-सर्वर पर एक छोटे डेटासेट पर, यह एक आकर्षण की तरह काम करता था, लेकिन उत्पादन वातावरण में इसने एक त्रुटि दी। इसलिए, मैंने दो बार आईडी की सूची की लंबाई कम कर दी, लेकिन इसका कोई फायदा नहीं हुआ।

अगली बात मैंने कोशिश की थी कि सूची में प्रत्येक आईडी को अद्यतन विवरण ("UPDATE yyy SET booleanfield = 1 WHERE id = '{id}'") में बदल दिया जाए। कहीं, मैंने पढ़ा है कि प्रत्येक एक्स लाइनों की संख्या में जाना अच्छा है, इसलिए मैंने प्रत्येक 100 लाइनों को एक गो डाला (उत्कृष्ट 'sed' टूल का उपयोग करके, यूनिक्स से पोर्ट किया गया)।

इसलिए, मैंने 250,000 प्रत्येक के हिस्सों में 4 मिलियन अपडेट स्टेटमेंट्स की सूची को अलग किया, उन्हें एसक्यूएल फाइलों के रूप में सहेजा और SQL सर्वर प्रबंधन स्टूडियो (2008) में पहले लोडिंग और चलाने शुरू कर दिया। ध्यान दें कि मैंने SQLCMD.exe को भी आजमाया है, लेकिन यह, मेरे आश्चर्य के लिए, एसक्यूएल स्टूडियो की तुलना में लगभग 10-20 गुना धीमा रहा।

इसे पूरा करने में लगभग 1,5 घंटे लग गए और परिणामस्वरूप "त्रुटियों के साथ क्वेरी समाप्त हुई"। हालांकि, संदेशों की सूची में "1 पंक्ति (ओं) प्रभावित" और "0 पंक्तियां प्रभावित" की एक अच्छी सूची थी, बाद में जब आईडी नहीं मिली थी।

अगला, मैंने COUNT (*) का उपयोग करके तालिका में अद्यतन रिकॉर्ड्स की मात्रा की जांच की और पाया कि अद्यतन विवरणों की मात्रा और अद्यतन रिकॉर्ड्स की मात्रा के बीच कुछ हज़ार रिकॉर्ड का अंतर था।

मैंने सोचा कि यह अस्तित्वहीन रिकॉर्ड के कारण हो सकता है, लेकिन जब मैंने आउटपुट में "0 पंक्तियों को प्रभावित" की मात्रा को घटा दिया, तो 8 9 5 रिकॉर्डों का एक रहस्यमय अंतर था।

मेरे सवालों का:

  1. वहाँ किसी भी तरह से एक विवरण और में त्रुटियों का कारण पता लगाने के लिए है "क्वेरी त्रुटियों के साथ पूर्ण।"

  2. 895 अभिलेखों के रहस्यमय अंतर को कैसे समझाया जा सकता है?

  3. इस अद्यतन को करने के लिए बेहतर, या सबसे अच्छा तरीका क्या है?

+0

गैप या तो इस तथ्य से जुड़ा हुआ प्रतीत होता है कि आपके पास डुप्लिकेट आईडी (जो निश्चित रूप से 4 मिलियन रिकॉर्ड के साथ एक संभावना है) या आईडी के बिन तालिका (एक और संभावना) मौजूद नहीं है। –

+0

आपने उन 4 मिल रिकॉर्ड को सीएसवी स्ट्रिंग में कैसे प्राप्त किया? – Kaf

+0

कुल तालिका में कितने रिकॉर्ड हैं? मैं सोच रहा हूं कि अगर 4 मिलियन से अधिक हैं, तो कॉलम को छोड़ना बेहतर होगा, इसे 1 के डिफ़ॉल्ट के साथ जोड़ें, और अन्य पंक्तियों को 0 या शून्य पर अपडेट करें। – UnhandledExcepSean

उत्तर

6

इस पूछने के लिए सबसे अच्छा तरीका एक टेबल में 4 मिलियन रिकॉर्ड डालने से है। वास्तव में, आप उन्हें एक दृश्य कॉलम के साथ एक तालिका में "थोक डालने" द्वारा देख सकते हैं।

create table TheIds (rownum int identity(1,1), id int); 

create view v_TheIds (select id from TheIds); 

bulk insert into v_TheIds . . . 

डेटाबेस में सभी डेटा के साथ, अब आपके पास कई और विकल्प हैं। अद्यतन का प्रयास करें:

update t 
    set booleanfield = 1 
    where exists (select 1 from TheIds where TheIds.id = t.id) 

तुम भी TheIds(id) पर एक सूचकांक बनाना चाहिए।

यह एक बड़ा अपडेट है, जो सभी एक लेनदेन के रूप में निष्पादित होते हैं। इसमें खराब प्रदर्शन प्रभाव हो सकते हैं और लॉग भरना शुरू कर सकते हैं। आप rownum स्तंभ का उपयोग छोटे लेनदेन में इसे तोड़ सकते हैं:

update t 
    set booleanfield = 1 
    where exists (select 1 from TheIds where TheIds.id = t.id and TheIds.rownum < 1000) 

खंड मौजूद है यहाँ left outer join के बराबर कर रही है। मुख्य अंतर यह है कि इस सहसंबंधित सबक्वायरी वाक्यविन्यास को अन्य डेटाबेस में काम करना चाहिए, जहां अद्यतनों के साथ जुड़ना डेटाबेस-विशिष्ट हैं।

rownum कॉलम के साथ, आप अपडेट के लिए जितनी चाहें उतनी पंक्तियों का चयन कर सकते हैं। इसलिए, यदि आप कुल अपडेट बहुत बड़ा है, तो आप अपडेट को लूप में डाल सकते हैं:

where rownum < 100000 
where rownum between 100000 and 199999 
where rownum between 200000 and 299999 

और इसी तरह। आपको ऐसा करने की ज़रूरत नहीं है, लेकिन आप कुछ कारणों से अपडेट बैच करना चाहते हैं।

मुख्य विचार डेटाबेस में किसी तालिका में आईडी की सूची प्राप्त करना है, ताकि आप बाद के संचालन के लिए डेटाबेस की शक्ति का उपयोग कर सकें।

+0

यह बहुत अच्छा लगता है और बहुत आसान लगता है, जो कि ज्यादातर मामलों में सबसे अच्छा है :) धन्यवाद बहुत गॉर्डन, इसे आजमाएं और परिणाम यहां पोस्ट करेंगे। –

+0

यह अविश्वसनीय है कि एसक्यूएल सर्वर द्वारा तालिका में 4 मिलियन आईडी कितनी तेजी से डाली जाती हैं ... मैं आश्चर्यचकित हूं। अब तक सब ठीक है. मुझे यकीन नहीं है कि "द आईड्स से चुनें 1 जहां TheIds.id = t.id और TheIds.rownum <1000" के संबंध में आपका मतलब है "आप इसे राउनम कॉलम का उपयोग करके छोटे लेनदेन में तोड़ सकते हैं"। क्या आप कृपया समझा सकते हैं? –

+0

मैंने राउनंबर 'चाल' का उपयोग करके 4 मिलियन में 8 भागों में कटौती की और एक घंटे से भी कम समय में सभी 4 मिलियन रिकॉर्ड अपडेट कर दिया। चौका देने वाला। धन्यवाद गॉर्डन! –

4

चेतावनी (मैं क्या मैं बहुत अक्षम और/या त्रुटि प्रवण हो सकता है कर रहा हूँ सोचने के लिए शुरू कर के रूप में): मैं यह परीक्षण करने के लिए नहीं कर पाए हैं और मैं एक "डेटाबेस खेल का मैदान नहीं है "जो उस डेटा को पकड़ सकता है।

मैं 1. और 2. बारे में निश्चित नहीं हूँ, लेकिन 3 के लिए आप डीबी करने के लिए अद्यतन की सीमित छोड़ने से बेहतर होना चाहिए:

UPDATE TOP(100000) yyy 
SET booleanfield = 1 
WHERE booleanfield = 0 
GO 

हालांकि प्रलेखन "बेतरतीब ढंग से चुनें" करने के लिए कुछ का कहना है उस टॉप-सीमा के साथ प्रविष्टियां - मुझे उम्मीद है कि यह केवल booleanfield = 0 वाले लोगों से ऐसा ही करता है। उस क्वेरी को बार-बार चलाएं जब तक कि कोई और अपडेट न हो।

एक अन्य विकल्प अगर ऊपर काम नहीं करता है DB से सीधे प्रभावित आईडी चयन करने के लिए है ... यह अजीब लग रहा है और मैं या तो यह परीक्षण नहीं किया है, लेकिन मुझे उम्मीद है कि यह काम करता है:

UPDATE yyy 
SET booleanfield = 1 
FROM (SELECT TOP 100000 id FROM yyy WHERE booleanfield = 0 ORDER BY id ASC) AS xxxx 
WHERE yyy.id = xxxx.id; 
GO 

(मुझे लगता है कि यहां तालिका में आपके पास एक अद्वितीय कुंजी id है)। इस क्वेरी को कई (लगभग 40) बार चलाएं जब तक कि कोई और अपडेट न हो।

+0

क्लेमेंस, मुझे टॉप() चाल के बारे में पता नहीं था। जानकार अच्छा लगा। धन्यवाद –

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

  • कोई संबंधित समस्या नहीं^_^