2012-07-10 44 views
49

हम अपने डीबी सर्वर के रूप में Postgresql 9.1.4 का उपयोग कर रहे हैं। मैं अपने टेस्ट सूट को तेज करने की कोशिश कर रहा हूं, इसलिए मैंने यह देखने के लिए थोड़ा सा डीबी प्रोफाइलिंग करना देखा है कि क्या हो रहा है। परीक्षण के अंत में हम टेबल को छंटनी करने के लिए database_cleaner का उपयोग कर रहे हैं। हां, मुझे पता है कि लेनदेन तेजी से हैं, मैं कुछ परिस्थितियों में उनका उपयोग नहीं कर सकता, इसलिए मैं इससे चिंतित नहीं हूं।पोस्टग्रेस्क्ल ट्रंकेशन गति

जो मुझे चिंतित है, यही कारण है कि ट्रंकेशन इतना लंबा लगता है (DELETE का उपयोग करने से अधिक लंबा) और यह मेरे सीआई सर्वर पर भी लंबे समय तक क्यों लेता है।

अभी, स्थानीय रूप से (मैकबुक एयर पर) एक पूर्ण परीक्षण सुइट में 28 मिनट लगते हैं। लॉग पीछा, हर बार जब हम टेबल काटना ... यानी:

TRUNCATE TABLE table1, table2 -- ... etc 

यह दूसरा 1 कार्यभार संभाला काट-छांट करने के लिए। हमारे सीआई सर्वर (उबंटू 10.04 एलटीएस) पर लॉग को लेकर, टेबल को छोटा करने के लिए एक पूर्ण 8 सेकंड लगते हैं और एक बिल्ड में 84 मिनट लगते हैं।

जब मैंने :deletion रणनीति पर स्विच किया, तो मेरे स्थानीय निर्माण में 20 मिनट लग गए और सीआई सर्वर 44 मिनट तक चला गया। यह महत्वपूर्ण अंतर है और मैं वास्तव में क्यों उड़ा हूं कि यह क्यों हो सकता है। मेरे पास tunedthe सीआई सर्वर पर डीबी है, इसमें 16 जीबी सिस्टम रैम, 4 जीबी साझा_बफर ... और एक एसएसडी है। सभी अच्छी चीजें यह कैसे संभव है:

ए। कि यह मैकबुक एयर से 2 जीबी रैम
बी के साथ बहुत धीमी है। कि TRUNCATION DELETE से बहुत धीमी है जब postgresql docsstate explicitly यह बहुत तेज़ होना चाहिए।

किसी भी विचार?

+0

क्या आप मैकबुक पर परीक्षण और डेटाबेस चला रहे हैं, और सीआई सर्वर पर परीक्षण और डेटाबेस चला रहे हैं? एक ही मशीन पर परीक्षण और डेटाबेस हैं? –

+1

बीटीडब्ल्यू, आप इसे गलत कर रहे हैं ... आप परीक्षण के बाद डेटाबेस को साफ़ नहीं कर सकते हैं। परीक्षण चलाने से पहले आपको इसे करना चाहिए। आप यह सुनिश्चित नहीं कर सकते कि डेटाबेस परीक्षण के बाद साफ़ हो गया है। –

+0

क्या postgresql.conf पैरामीटर उपयोग में हैं? मैं सोच रहा हूं कि क्या आप fsync = off के साथ चल रहे हैं (ठीक है अगर आपको परीक्षण में जैसे सभी डेटा खोने में कोई फर्क नहीं पड़ता) तो इस मामले में 'DELETE' और' TRUNCATE' के बीच की शेष राशि अलग हो सकती है। मुझे आपके 'shared_buffers' में रुचि भी होगी। –

उत्तर

121

यह एसओ और पोस्टग्रेएसक्यूएल मेलिंग सूचियों पर हाल ही में कुछ बार आया है।

टी एल; डॉ अपने अंतिम दो अंक के लिए:

(क) बड़ा shared_buffers हो सकता है क्यों TRUNCATE सीआई सर्वर पर धीमी है। विभिन्न fsync विन्यास या एसएसडी के बजाय घूर्णन मीडिया का उपयोग भी गलती हो सकती है।

(बी) TRUNCATE की एक निश्चित लागत है, लेकिन DELETE से ज़रूरी नहीं है, और यह अधिक काम करता है। निम्नानुसार विस्तृत स्पष्टीकरण देखें।

अद्यतन:significant discussion on pgsql-performance इस पोस्ट से उत्पन्न हुआ। this thread देखें।

अद्यतन 2: सुधार 9.2beta3 में जोड़ा गया है जो इसके साथ मदद करनी चाहिए, this post देखें।

का विस्तृत विवरण TRUNCATE बनाम DELETE FROM:

जबकि विषय पर एक विशेषज्ञ, मैं समझता हूँ कि TRUNCATE, तालिका के अनुसार लगभग एक निश्चित मूल्य है DELETE एन पंक्तियों के लिए कम से कम हे (एन) है, जबकि है ; बदतर होने पर तालिका को संदर्भित करने वाली कोई भी विदेशी कुंजी है तो बदतर।

मुझे हमेशा लगता है कि TRUNCATE की निश्चित लागत DELETE की लागत से कम खाली तालिका पर कम थी, लेकिन यह बिल्कुल सही नहीं है।

TRUNCATE table; से अधिक DELETE FROM table;

करता है एक TRUNCATE table के बाद डेटाबेस के राज्य के रूप में यदि आप के बजाय चलाने चाहते हैं ज्यादा एक ही है:

  • DELETE FROM table;
  • VACCUUM (FULL, ANALYZE) table; (केवल 9.0+ , फुटनोट देखें)

... हालांकि TRUNCATE वास्तव में DELETE और VACUUM के साथ अपने प्रभाव प्राप्त नहीं करता है।

बिंदु यह है कि DELETE और TRUNCATE अलग-अलग चीजें करते हैं, इसलिए आप समान परिणामों के साथ दो आदेशों की तुलना नहीं कर रहे हैं।

एक DELETE FROM table;, टेबल क्वेरी योजनाकार द्वारा इस्तेमाल किया आंकड़ों को अपडेट नहीं करता है, आदि

एक TRUNCATE आप एक पूरी तरह से नई तालिका देता है और मृत पंक्तियों और रहने के लिए अनुमति देता है ब्लोट अनुक्रमित मृत प्रविष्टियों ले जाने के लिए अनुमति देता है, इंडेक्स जैसे कि वे CREATE एड थे। ऐसा लगता है कि आपने सभी रिकॉर्ड्स हटा दिए हैं, टेबल को दोबारा बनाया है और VACUUM FULL किया है।

यदि आपको कोई परवाह नहीं है कि तालिका में क्रूड छोड़ा गया है क्योंकि आप इसे जाने और फिर से भरने जा रहे हैं, तो आप DELETE FROM table; का उपयोग कर बेहतर हो सकते हैं।

क्योंकि आप VACUUM नहीं चला रहे हैं, तो आप पाएंगे कि मृत पंक्तियां और इंडेक्स प्रविष्टियां ब्लोट के रूप में जमा होती हैं जिन्हें स्कैन किया जाना चाहिए और फिर अनदेखा किया जाना चाहिए; यह आपके सभी प्रश्नों को धीमा कर देता है। यदि आपके परीक्षण वास्तव में उन सभी डेटा को नहीं बनाते और हटाते हैं जिन्हें आप नोटिस या देखभाल नहीं कर सकते हैं, और यदि आप करते हैं तो आप हमेशा अपने परीक्षण चलाने के माध्यम से VACUUM या दो भाग-मार्ग कर सकते हैं। बेहतर, आक्रामक ऑटोवाक्यूम सेटिंग्स को सुनिश्चित करें कि ऑटोवाक्यूम पृष्ठभूमि में आपके लिए यह करता है।

तुम अब भी TRUNCATE आपके सभी तालिकाओं के बाद पूरे टेस्ट स्वीट सुनिश्चित करें कि कोई प्रभाव कई रन के पार का निर्माण करने के लिए चलाता कर सकते हैं। 9.0 और नए, VACUUM (FULL, ANALYZE); तालिका पर विश्व स्तर पर कम से कम उतना ही अच्छा है जितना बेहतर नहीं है, और यह एक बहुत आसान है।

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

DELETE FROM table; कोई f/कश्मीर refs यह करने के लिए कोई विदेशी कुंजी संदर्भ के साथ

एक मेज से DELETE सभी रिकॉर्ड करने के लिए के साथ छोटे तालिकाओं के लिए बहुत सस्ता है, सभी पृष्ठ एक अनुक्रमिक तालिका स्कैन करते हैं और स्थापित करने के लिए है Tuples का xmax सामना करना पड़ा। यह एक बहुत सस्ता ऑपरेशन है - मूल रूप से एक रैखिक पढ़ने और अर्ध-रैखिक लेखन। AFAIK इसे सूचकांक को छूने की जरूरत नहीं है; जब तक वे बाद में VACUUM तक साफ़ नहीं हो जाते हैं, तब तक वे मृत टपल्स को इंगित करते रहते हैं, जिसमें तालिका में केवल ब्लू ट्यूपल्स युक्त ब्लॉक होते हैं।

DELETE केवल महंगा हो जाता है, अगर वहाँ है, अगर वहाँ विदेशी कुंजी संदर्भ के बहुत सारे है कि जाँच की जानी चाहिए रहे हैं बहुत सारे रिकॉर्ड की हैं, या यदि आप बाद में VACUUM (FULL, ANALYZE) table; अपने DELETE की लागत के भीतर TRUNCATE के प्रभाव से मेल करने के लिए आवश्यक गिनती ।

मेरे परीक्षणों में, DELETE FROM table; आमतौर पर TRUNCATE से 4x तेज 0.5 मिमी बनाम 2ms पर था। यह एक एसएसडी पर एक परीक्षण डीबी है, fsync=off के साथ चल रहा है क्योंकि मुझे कोई परवाह नहीं है कि मैं यह सब डेटा खो देता हूं। बेशक, DELETE FROM table; सभी एक ही काम नहीं कर रहा है, और यदि मैं VACUUM (FULL, ANALYZE) table; के साथ अनुवर्ती हूं तो यह अधिक महंगा 21ms है, इसलिए DELETE केवल एक जीत है यदि मुझे वास्तव में टेबल प्रिस्टिन की आवश्यकता नहीं है।

TRUNCATE table;, एक बहुत अधिक निर्धारित लागत काम और DELETE

इसके विपरीत से गृह व्यवस्था करता है एक TRUNCATE बहुत काम करना है। इसे तालिका के लिए नई फाइलों को आवंटित करना होगा, यदि कोई हो, तो TOAST तालिका, और तालिका में प्रत्येक अनुक्रमणिका है। हेडर को उन फ़ाइलों में लिखा जाना चाहिए और सिस्टम कैटलॉग को भी अपडेट करने की आवश्यकता हो सकती है (उस बिंदु पर सुनिश्चित नहीं है, चेक नहीं किया है)। इसके बाद पुरानी फाइलों को नए लोगों के साथ बदलना होगा या पुराने लोगों को हटा देना होगा, और यह सुनिश्चित करना होगा कि फ़ाइल सिस्टम सिंक्रनाइज़ेशन ऑपरेशन के साथ परिवर्तनों के साथ पकड़ा गया है - fsync() या इसी तरह - जो आमतौर पर सभी बफर डिस्क पर फ़्लश करता है । मुझे यकीन नहीं है कि अगर आप (डेटा खाने) विकल्प fsync=off के साथ चल रहे हैं तो सिंक छोड़ा गया है या नहीं।

मैंने हाल ही में सीखा है कि TRUNCATE को पुरानी तालिका से संबंधित सभी पोस्टग्रेएसक्यूएल के बफर को भी फ्लश करना होगा। यह विशाल shared_buffers के साथ एक गैर-तुच्छ समय ले सकता है। मुझे संदेह है कि यही कारण है कि यह आपके सीआई सर्वर पर धीमा है।

संतुलन

वैसे भी, आप देख सकते हैं कि एक संबद्ध टोस्ट मेज है कि एक तालिका (सबसे अधिक है) और कई इंडेक्सों का एक TRUNCATE कुछ पल ले सकता है। लंबे समय तक नहीं, लेकिन निकटतम तालिका से DELETE से अधिक लंबा है।

परिणामस्वरूप, आप DELETE FROM table; करने से बेहतर हो सकते हैं।

-

नोट: डीबीएस पर पहले 9.0, CLUSTER table_id_seq ON table; ANALYZE table; या VACUUM FULL ANALYZE table; REINDEX table;TRUNCATE करने के लिए एक करीब बराबर होगा। VACUUM FULL इंप्रेशन 9.0 में एक बेहतर बेहतर में बदल गया।

+3

नहीं है और उनके पास अलग-अलग प्रकार के ताले हैं: टेबल लॉक बनाम पंक्ति लॉक। –

+0

व्यापक उत्तर के लिए धन्यवाद! दस्तावेज़ों के अनुसार >> यह [TRUNCATE] का प्रत्येक तालिका पर एक अयोग्य डिलीट के समान प्रभाव होता है, लेकिन चूंकि यह वास्तव में तालिकाओं को स्कैन नहीं करता है, यह तेज़ है। इसके अलावा, यह बाद के वाक्यूम ऑपरेशन की आवश्यकता के बजाय तुरंत डिस्क स्थान पुनः प्राप्त करता है। >> इसलिए मुझे लगता है कि यह वास्तव में एक छंटनी के बाद वैक्यूम नहीं लगता है। क्या आप यह भी सुझाव दे रहे हैं कि तथ्य यह है कि मेरे पास 4 जीबी साझा_बफर वास्तव में प्रदर्शन का नुकसान है? – brad

+0

@brad 'TRUNCATE' के विशिष्ट मामले के लिए, हाँ, मैं कह रहा हूं कि मेरी समझ यह है कि बड़े 'shared_buffers' चीजों को धीमा कर सकते हैं।मैंने खुद का परीक्षण नहीं किया है, लेकिन यह एमएल चर्चा से ऐसा लगता है। और नहीं, एक छंटनी के बाद कोई 'वैक्यूम' नहीं किया जाता है - जबकि छंटनी * का * एक 'विलुप्त पूर्ण' का प्रभाव होता है, जिसके बाद 'वैक्यूम पूर्ण विश्लेषण' होता है, यह वास्तव में उस तरह से काम नहीं करता है या उन चरणों को निष्पादित नहीं करता है। –

0

वैकल्पिक तरीकों में से एक जोड़े को विचार करने के लिए:

  • उस में स्थिर "स्थिरता" डेटा के साथ एक खाली डेटाबेस बनाएँ, और कि में परीक्षण चला। जब आप कर लेंगे, बस डेटाबेस को छोड़ दें, जो तेज़ होना चाहिए।
  • "test_ids_to_delete" नामक एक नई तालिका बनाएं जिसमें तालिका के नाम और प्राथमिक कुंजी आईडी के लिए कॉलम हों। इसके बजाय इस तालिका में आईडी/तालिका नाम डालने के लिए अपना विलोपन तर्क अपडेट करें, जो चलने वाले डेलेट से कहीं अधिक तेज़ होगा। फिर, संपूर्ण टेस्ट रन समाप्त होने के बाद, या रातोंरात डेटा को वास्तव में हटाने के लिए "ऑफ़लाइन" चलाने के लिए एक स्क्रिप्ट लिखें।

पूर्व एक "साफ कमरा" दृष्टिकोण है, जबकि बाद का मतलब है कि कुछ परीक्षण डेटा लंबे समय तक डेटाबेस में बने रहेंगे। ऑफलाइन डिलीट के साथ "गंदा" दृष्टिकोण वह है जो मैं परीक्षण सूट के लिए लगभग 20,000 परीक्षणों के साथ उपयोग कर रहा हूं। हां, कभी-कभी समस्याएं डेटाबेस डेटाबेस में "अतिरिक्त" परीक्षण डेटा होने के कारण होती हैं लेकिन कभी-कभी। लेकिन कभी-कभी इस "गंदगी" ने हमें बग को खोजने और ठीक करने में मदद की है क्योंकि "गड़बड़ी" ने वास्तविक दुनिया की स्थिति को बेहतर तरीके से अनुकरण किया है, इस तरह से साफ-सुथरा कमरा कभी नहीं होगा।

5

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

संबंधित प्रश्न: 30 tables with few rows - TRUNCATE the fastest way to empty them and reset attached sequences?

कृपया यह भी इस मुद्दे पर देखो और इस पुल का अनुरोध:

https://github.com/bmabey/database_cleaner/issues/126

https://github.com/bmabey/database_cleaner/pull/127

इसके अलावा इस सूत्र: http://archives.postgresql.org/pgsql-performance/2012-07/msg00047.php

मैं के लिए माफी चाहता हूँ इसे एक उत्तर के रूप में लिखना, लेकिन मुझे कोई नहीं मिला एनई टिप्पणी लिंक, शायद क्योंकि वहाँ पहले से ही बहुत अधिक टिप्पणियां हैं।

+0

हे धन्यवाद stanislaw। मैंने वास्तव में उन पदों को देखा जो मुझे द्रव्यमान छंटनी का उपयोग करने के लिए डीबी क्लीनर को अपग्रेड करने के लिए प्रेरित करते थे। हालांकि, मेरी मदद करने के लिए बहुत कम किया। अभी भी पीजी पर ऐसा लगता है कि हटाना रणनीति काफी तेज है, जो मैंने उपयोग कर समाप्त कर दी है। – brad