यह एसओ और पोस्टग्रेएसक्यूएल मेलिंग सूचियों पर हाल ही में कुछ बार आया है।
टी एल; डॉ अपने अंतिम दो अंक के लिए:
(क) बड़ा 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 में एक बेहतर बेहतर में बदल गया।
क्या आप मैकबुक पर परीक्षण और डेटाबेस चला रहे हैं, और सीआई सर्वर पर परीक्षण और डेटाबेस चला रहे हैं? एक ही मशीन पर परीक्षण और डेटाबेस हैं? –
बीटीडब्ल्यू, आप इसे गलत कर रहे हैं ... आप परीक्षण के बाद डेटाबेस को साफ़ नहीं कर सकते हैं। परीक्षण चलाने से पहले आपको इसे करना चाहिए। आप यह सुनिश्चित नहीं कर सकते कि डेटाबेस परीक्षण के बाद साफ़ हो गया है। –
क्या postgresql.conf पैरामीटर उपयोग में हैं? मैं सोच रहा हूं कि क्या आप fsync = off के साथ चल रहे हैं (ठीक है अगर आपको परीक्षण में जैसे सभी डेटा खोने में कोई फर्क नहीं पड़ता) तो इस मामले में 'DELETE' और' TRUNCATE' के बीच की शेष राशि अलग हो सकती है। मुझे आपके 'shared_buffers' में रुचि भी होगी। –