SQL सर्वर "खाली तालिका" सभी (12 मिलियन) रिकॉर्ड को हटाने के बाद धीमा है?


27

मेरे पास लगभग 150 कॉलम के साथ SQL Server 2008 का उदाहरण है। मैंने पहले इस तालिका को लगभग 12 मिलियन प्रविष्टियों के साथ आबाद किया है, लेकिन तब से एक नए डेटा सेट की तैयारी में तालिका को मंजूरी दे दी है।

हालांकि, आदेश होते हैं जो एक बार एक खाली टेबल पर तुरन्त दौड़ा जैसे count(*)और select top 1000में SQL Management Studioअब चलाने के लिए युगों से लेते हैं।

SELECT COUNT(*) FROM TABLE_NAME 

0 लौटने में 11 मिनट से अधिक समय लगा, और SELECT TOP 1000एक खाली टेबल पर लौटने में लगभग 10 मिनट लगे।

मैंने यह भी देखा है कि मेरी हार्ड ड्राइव पर मुक्त स्थान सचमुच गायब हो गया है (लगभग 100G से 20G तक)। केवल एक चीज जो मेरे बीच हुई थी, वह थी:

DELETE FROM TABLE_NAME

दुनिया में क्या चल रहा है?!?


5
आपका डेटाबेस किस रिकवरी मॉडल का उपयोग करता है? यदि यह "पूर्ण" है, तो आपका SQL उदाहरण उन सभी विलोपन का एक रिकॉर्ड संग्रहीत करेगा, जो हो सकता है कि आपका खाली स्थान कहाँ गया था। यदि पूर्ण पुनर्प्राप्ति एक आवश्यकता है, तो मैं TRUNCATE TABLEइसके बजाय का उपयोग करने की सलाह देता हूं DELETE FROM
तुललो_एक्स

2
150 कॉलम? वह तालिका ओवरऑल हो सकती है - अधिकांश ट्यूपल्स छोटे होने चाहिए। हालांकि, पूरे संदर्भ के बिना कहना असंभव है।
क्लॉकवर्क-म्यूज़ियम

जवाबों:


42

आपको पहले से ही इस बारे में बताया TRUNCATEजा चुका है कि इतना तेज़ / बेहतर / कामुक क्यों होगा DELETE, लेकिन अभी भी एक सवाल बाकी है:

पूराSELECT होने के बाद धीमा क्यों है ?DELETE

ऐसा इसलिए है क्योंकि DELETEकेवल पंक्तियों में भूत है। तालिका केवल उतनी ही बड़ी है, जब इसमें 12M पंक्तियाँ थीं, हालांकि इसमें कोई नहीं है। पंक्तियों (0) को गिनने के लिए, 12M पंक्तियों को गिनने में जितना समय लगता है, उतना ही समय लगता है। समय में भूत की सफाई प्रक्रिया इन भूतों के रिकॉर्ड को इकट्ठा करेगी और केवल भूतों को शामिल करने वाले पृष्ठों को हटाएगी, और आपके चयन में तेजी आएगी। लेकिन अभी अगर आप Skipped Ghosted Records/secपरफ्यूम में जांच करते हैं, तो शायद इस दौरान आसमान छू रहा है SELECT COUNT(*)। आप टेबल को पुनर्निर्माण करके चीजों को गति भी दे सकते हैं ALTER TABLE ... REBUILD:।

TRUNCATE इस समस्या का भी ध्यान रखा होगा, क्योंकि यह कोई भूत नहीं छोड़ता है।

स्टोरेज इंजन के अंदर भी देखें : गहराई में भूत सफाई


13

DELETEकथन एक बार में एक तालिका से पंक्तियों को हटाते हैं, प्रत्येक पंक्ति को लॉगिंग करते हैं transaction log, साथ ही साथ log sequence number (LSN)जानकारी को बनाए रखते हैं। चूँकि आपने उल्लेख किया था कि आपकी तालिका में बहुत बड़ा डेटा (12 मिलियन रिकॉर्ड) था, जिसके विलोपन के बाद आपकी हार्ड डिस्क अंतरिक्ष से बाहर हो गई है, अपने डेटाबेस लॉग फ़ाइल के आकार की जाँच करें। यह शायद सबसे बड़ा होगा।

एक बेहतर तरीका होता:

TRUNCATE TABLE_NAME

2
+1, ओरेकल डीबी के लिए बिल्कुल सही है। यदि आप उन बयानों का उपयोग करते हैं जो रिकॉर्ड करने के लिए लॉग करते हैं तो यह समय के साथ डेटाबेस को धीमा कर देगा।
पेट्रो सेमेनीयुक

@PetroSemeniuk ओरेकल पर मुझे जो याद आता है, उसमें से अकेले हाईवा मार्क को छोड़ दें, ट्रंकट हाई वॉटर मार्क को रीसेट कर देगा। मेरा मानना ​​है कि किसी भी संचालन के लिए एक पूर्ण स्कैन की आवश्यकता होती है जो उच्च पानी के निशान तक ब्लॉकों को स्कैन करेगा। इसलिए हटाने से अनुक्रमित संचालन में सहायता मिल सकती है, लेकिन स्कैन नहीं। TRUNCATE उचित संचालन था।
ग्लेन

3

(यह मूल रूप से @ डेव के जवाब के लिए एक टिप्पणी थी, लेकिन मैंने इसे अपने स्वयं के उत्तर में डाल दिया है क्योंकि यह लंबा हो गया है)

TRUNCATE है एक लॉग इन आपरेशन। यह अन्यथा ACID के अनुरूप नहीं होना चाहिए। हालाँकि, के बीच अंतर TRUNCATEऔर DELETE:

  • लॉग स्पेस का उपयोग करें: TRUNCATEकेवल लॉग पेज / एक्स्टेंट * फ़्री किया गया है, जबकि DELETEव्यक्तिगत पंक्तियों को लॉग करता है।
  • लॉक का उपयोग: TRUNCATEआमतौर पर कम ताले का उपयोग करेगा, क्योंकि यह टेबल लॉक और पेज लॉक लेता है, DELETEजिसके विपरीत पंक्ति ताले का उपयोग करता है **।
  • IDENTITYअनुक्रम: TRUNCATEएक मेज पर पहचान अनुक्रम को रीसेट करता है, यदि मौजूद हो।

(* एक सीमा = 8 पृष्ठ। TRUNCATEयदि वे उस एक तालिका से हैं, तो वे सभी लॉग लॉग / निकाल देंगे, अन्यथा यह अन्य अतिरिक्त पेजों से लॉग इन / पेज हटा देगा।

** इसका एक दुष्प्रभाव यह है कि DELETE FROM TABLEसंभावित रूप से तालिका में आवंटित खाली पृष्ठों को छोड़ दिया जा सकता है, इस पर निर्भर करता है कि ऑपरेशन एक अनन्य लॉक प्राप्त कर सकता है या नहीं।)

इसलिए (मूल प्रश्न पर वापस), यदि आप तालिका को खाली कर रहे हैं , तो TRUNCATE TABLEयह निर्णायक रूप से बेहतर है , DELETE FROM TABLEलेकिन संरचना को रखना चाहते हैं (NB: TRUNCATEएक मेज पर उपयोग नहीं किया जा सकता है जिसे किसी अन्य तालिका से एक विदेशी कुंजी द्वारा संदर्भित किया जाता है)।

जैसा कि @ टुल्लो की टिप्पणी में उल्लेख किया गया है, अपने डेटाबेस के रिकवरी मॉडल को भी देखें - यदि यह पूर्ण है, तो आपको या तो लॉग बैकअप लेना शुरू करना होगा, या अपने रिकवरी मॉडल को सरल में बदलना होगा। एक बार जब आप दोनों में से किसी एक को पूरा कर लेते हैं, तो संभवत : उस सभी रिक्त स्थान को पुनः प्राप्त करने के लिए आप अपनी लॉग फ़ाइल को एक बार-बंद ऑपरेशन (NB: लॉग फ़ाइल केवल ) के रूप में सिकोड़ना चाहेंगे ।

अंत में, एक और बात के बारे में पता होना चाहिए - तालिका आँकड़े। चलाने UPDATE STATISTICS <TABLENAME>' afterTRUNCATE /DELETE` तो क्वेरी अनुकूलक पुराने आंकड़े से ऊपर फिसल न हो।


2

(नोट: मैं डीबीए नहीं हूं) DELETE एक लॉग ऑपरेशन है, और यह उपयोग किए गए स्थान को मुक्त नहीं करता है। संभवत: आपके पास 'खाली' टेबल स्थान पर चलने वाले स्थान और टेबल स्कैन के लिए एक बड़ा लेनदेन लॉग है। मुझे लगता है कि आपको लेन-देन लॉग साफ़ करने और अपने डेटाबेस को सिकोड़ने की आवश्यकता है। यह StackOverflow लेख आपको आरंभ करना चाहिए।

और TRUNCATE TABLE का उपयोग करें जब आप भविष्य में ऐसा करना चाहते हैं।

संपादित करें: TRUNCATE के बारे में मेरा कथन लॉग नहीं किया जा रहा है, त्रुटि थी। हटा दिया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.