2010-01-17 4 views
9

हटाने गतिविधियों जहां unt_uid रिक्त हैकैसे-एसक्यूएल सर्वर पर एक मेज से 8,500,000 रिकॉर्ड्स को हटाना

सबसे तेज़ तरीका होगा, लेकिन जब तक इस बयान समाप्त हो गया है कोई भी डेटाबेस/तालिका का उपयोग कर सकते तो यह एक नहीं- है चले जाओ।

मैंने काम करने के दौरान यह कार्य करने के लिए एक कर्सर को परिभाषित किया लेकिन वैसे भी उत्पादकता पर असर बड़ा है। तो इन रिकॉर्ड को कैसे हटाएं ताकि इस डेटाबेस के सामान्य उपयोग की गारंटी हो?

यह 32-बिट Win2003 पर SQL-2005 सर्वर है। दूसरा सवाल यह है कि आप इस नौकरी के लिए कब तक अनुमान लगाएंगे (6 घंटे या 60 घंटे)? (हाँ, मुझे पता है कि लोड पर निर्भर करता है लेकिन मान लें कि यह एक छोटा व्यापार वातावरण है)

उत्तर

9

आप इसे टुकड़ों में कर सकते हैं। उदाहरण के लिए, हर 10 सेकंड निष्पादित करें:

delete from activities where activityid in 
    (select top 1000 activityid from activities where unt_uid is null) 

जाहिर पंक्ति संख्या को परिभाषित (मैं मनमाने ढंग से 1000 उठाया) और अंतराल (मैं 10 सेकंड उठाया) जो आपके आवेदन के लिए सर्वाधिक महत्व रखता है।

+0

इस संकेत के लिए धन्यवाद। मैं इसे एक कर्सर के साथ करूँगा जो शीर्ष 1000 का चयन करता है और इसे थोड़ी देर के साथ लपेटता है (चयन गिनती (*) ...)> 0. मुझे लगता है कि लेनदेन-लॉग एक और कहानी है: ऐसा करना संभव नहीं है लॉगिंग किए बिना हटाए जाने पर डेटाबेस का सामान्य उपयोग नियमित रूप से लॉग होता है? – Ice

+0

@ice मुझे ऐसा नहीं लगता है। आप थोक अपडेट के लिए लॉग बंद कर सकते हैं लेकिन हटाए नहीं जा सकते हैं। – Keltex

5

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

3

तालिका का उपयोग कौन कर सकता है आपके लेनदेन अलगाव मोड पर निर्भर करेगा, मुझे लगता है।

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

मेरी सबसे अच्छी सिफारिश आपके आवेदन को फिर से डिजाइन करना होगा ताकि आपको इन पंक्तियों या संभवतः किसी भी पंक्ति को हटाने की आवश्यकता न हो।

आप या तो तालिका को विभाजित करके ऐसा कर सकते हैं जैसे कि आप इसके बजाय विभाजन को छोड़ सकते हैं या "पंक्तियों की प्रतिलिपि बना सकते हैं जिन्हें आप रखना चाहते हैं, फिर तालिका को छोड़ दें" नुस्खा दूसरों द्वारा सुझाया गया है।

+0

विभाजन यह एक अच्छा विचार है: http://msdn.microsoft.com/en-us/library/ms345146(SQL.90).aspx –

+0

विभाजन हटाना करने से बचने का एक तरीका है, लेकिन केवल एकमात्र नहीं एक। – MarkR

0

एक छोटे से व्यवसाय के माहौल में, यह अजीब लगता है कि आपको किसी भी अन्य उपयोगकर्ताओं को प्रभावित किए बिना मानक परिचालन व्यवहार में 500,000 पंक्तियों को हटाने की आवश्यकता होगी। आम तौर पर बड़े पैमाने पर हटाए जाने के लिए, हम एक नई टेबल बना रहे हैं और पुराने को ओवरराइट करने के लिए TRUNCATE/INSERT या sp_rename का उपयोग कर रहे हैं।

यह कहकर कि, एक विशेष मामले में, मेरी मासिक प्रक्रियाओं में से एक नियमित रूप से लगभग 3 मीटर बैचों में 200 मीटर पंक्तियों को हटा सकती है, अगर यह पता चलता है कि उसे 200 मीटर पंक्तियों को उत्पन्न करने वाली प्रक्रिया को फिर से चलाने की आवश्यकता है। लेकिन यह एक समर्पित डेटा गोदाम डेटाबेस में एक एकल उपयोगकर्ता प्रक्रिया है, और मैं इसे एक लघु व्यवसाय परिदृश्य नहीं कहूंगा।

मैं आपके डिजाइन के वैकल्पिक दृष्टिकोण की मांग करने के उत्तर देने वाले उत्तरों को दूसरा स्थान देता हूं।

2

मैं "निबलिंग हटाने" तकनीक का उपयोग करूंगा। http://sqladvice.com/blogs/repeatableread/archive/2005/09/20/12795.aspx से:

DECLARE @target int 
SET @target = 2000 
DECLARE @count int 
SET @count = 2000 

WHILE @count = 2000 BEGIN 

DELETE FROM myBigTable 
WHERE targetID IN 
(SELECT TOP (@target) targetID 
    FROM myBigTable WITH(NOLOCK) 
    WHERE something = somethingElse) 

SELECT @count = @@ROWCOUNT 
WAITFOR DELAY '000:00:00.200' 

END 

मैं बिल्कुल परिदृश्य के इस प्रकार के लिए यह प्रयोग किया है। WAITFOR रखना महत्वपूर्ण है, यह अन्य प्रश्नों को हटाए जाने के बीच में अपना काम करने की अनुमति देता है।

+0

क्या आप इसके बजाय '@count <> 0' की जांच नहीं कर रहे हैं? अन्यथा, यदि पंक्तियों की संख्या 2000 –

+0

के साथ समान रूप से विभाजित नहीं होती है तो आप कुछ पंक्तियां छोड़ सकते हैं, वास्तव में यह काम करता है। उस मामले पर विचार करें जहां अंतिम डेलेटी 1337 पंक्तियां हैं। SELECT @count = @@ rowcount आपको 1337 प्राप्त करेगा, जबकि लूप-टाइम को समाप्त करेगा। –

+0

बेशक, यदि कोई ट्रिगर्स या कैस्केडिंग डिलीट हैं तो @@ rowcount बंद हो जाएगा। –

0

मैं इसके लिए एक कार्य तैयार करता हूं और इसे ऑफपेक घंटों के दौरान चलाने के लिए शेड्यूल करता हूं। लेकिन मैं आपको इस्तेमाल होने वाली तालिका में हटाने के लिए सुझाव नहीं दूंगा। उन पंक्तियों को ले जाएं जिन्हें आप नई तालिका में रखना चाहते हैं और वर्तमान तालिका को उन पंक्तियों से पूरी तरह से छोड़ दें जिन्हें आप हटाना चाहते हैं।

+0

मुझे लगता है कि यह [इस अन्य उत्तर] में शामिल था [http: // stackoverflow.com/a/2082767/573261) – RichardTheKiwi

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