पोस्टग्रेज से पंक्तियों को हटाने का सबसे कुशल तरीका है


23

मैं सोच रहा हूं कि PostgreSQL से बड़ी संख्या में पंक्तियों को हटाने के लिए सबसे कुशल तरीका क्या होगा, यह प्रक्रिया हर दिन एक आवर्ती कार्य का एक हिस्सा होगी जो डेटा आयात (एक प्रविष्टि + विलोपन का डेल्टा) को एक तालिका में बदल देती है। हटाने के लिए हजारों, संभवतः लाखों पंक्तियाँ हो सकती हैं।

मेरे पास प्राथमिक कुंजी की एक फ़ाइल है, प्रति पंक्ति एक। मैं जिन दो विकल्पों के बारे में सोच रहा था, वे नीचे की तर्ज पर थे, लेकिन मैं एक सूचित निर्णय लेने के लिए पोस्टग्रेसीक्यूएल के आंतरिक के बारे में पर्याप्त नहीं जानता / समझता हूं जो सबसे अच्छा होगा।

  • DELETEफ़ाइल में प्रत्येक पंक्ति के लिए एक क्वेरी निष्पादित करें , WHEREप्राथमिक कुंजी पर एक साधारण (या nकिसी IN()खंड का उपयोग करने वाले बैचों में समूह को हटाएं )
  • COPYकमांड का उपयोग करके एक अस्थायी तालिका में प्राथमिक कुंजियों को आयात करें और फिर एक सम्मिलित का उपयोग करके मुख्य तालिका से हटा दें

किसी भी सुझाव बहुत सराहना की जाएगी!


1
इसी प्रश्न का अधिक विस्तार से उत्तर यहां दिया गया है: stackoverflow.com/a/8290958
सिमोन

जवाबों:


25

आपका दूसरा विकल्प बहुत साफ है और इसके लायक बनाने के लिए पर्याप्त अच्छा प्रदर्शन करेगा। आपका विकल्प विशाल प्रश्नों का निर्माण करना है जो योजना बनाने और निष्पादित करने के लिए काफी दर्द होगा। सामान्य तौर पर आप बेहतर काम करने जा रहे हैं ताकि PostgreSQL यहां काम करे। सामान्य तौर पर, मैंने हजारों पंक्तियों में अपडेट किया है जिस तरह से आप पर्याप्त रूप से प्रदर्शन करने का वर्णन कर रहे हैं, लेकिन ऐसा करने से बचने के लिए एक महत्वपूर्ण बात है।

इसे करने का तरीका आपके डिलीट में सेलेक्ट और जॉइन का उपयोग करना है।

DELETE FROM foo WHERE id IN (select id from rows_to_delete);

किसी भी परिस्थिति में आपको एक बड़ी तालिका के साथ इस प्रकार नहीं होना चाहिए:

DELETE FROM foo WHERE id NOT IN (select id from rows_to_keep);

यह आमतौर पर एक नेस्टेड लूप एंटीजन के कारण होगा जो प्रदर्शन को समस्याग्रस्त बना देगा। यदि आप अंत में उस मार्ग पर जाना चाहते हैं, तो इसके बजाय यह करें:

DELETE FROM foo 
WHERE id IN (select id from foo f 
          LEFT JOIN rows_to_keep d on f.id = d.id
              WHERE d.id IS NULL);

PostgreSQL आमतौर पर बुरी योजनाओं से बचने में बहुत अच्छा है, लेकिन अभी भी बाहरी जुड़ने वाले मामले हैं जो अच्छी और बुरी योजनाओं के बीच एक बड़ा अंतर बना सकते हैं।

यह थोड़ा और दूर तक भटक रहा है, लेकिन मुझे यह ध्यान देने योग्य है कि IN से NOT में जाना और क्वेरी प्रदर्शन टैंक को देखना कितना आसान है।


यह एक बहुत मदद की, धन्यवाद! हालाँकि मैंने पाया कि "क्वेरीज़ को संयोजित करना" इस विशेष मामले में अधिक कुशल है। उदा। Postgresql.org/docs/9.4/static/queries-union.htmlIN ( select id from foo except select id from rows_to_keep )
Ufos

1

मैं इस सवाल पर आया क्योंकि मुझे इसी तरह की समस्या थी। मैं एक डेटाबेस की सफाई कर रहा हूं जिसमें 300M + पंक्तियाँ हैं, अंतिम डेटाबेस में मूल डेटा का लगभग 30% ही होगा। यदि आप एक समान परिदृश्य का सामना कर रहे हैं, तो वास्तव में हटाने के बजाय एक नई तालिका में सम्मिलित करना और पुन: अनुक्रमण करना आसान है।

कुछ ऐसा करो

CREATE temp_foo as SELECT * FROM foo WHERE 1=2;
INSERT INTO temp_foo (SELECT * FROM foo where foo.id IN (SELECT bar.id FROM BAR);

फू और बार पर उचित अनुक्रमण के साथ, आप Seq स्कैन से बच सकते हैं।

फिर आपको तालिका को फिर से अनुक्रमित और नाम बदलना होगा।

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