PostgreSQL में थोक अद्यतन प्रदर्शन का अनुकूलन


37

Ubuntu 12.04 पर PG 9.1 का उपयोग करना।

वर्तमान में किसी डेटाबेस पर बड़े स्टेटमेंट को सेट करने में हमें 24 घंटों तक का समय लगता है, जो इस प्रकार हैं:

UPDATE table
SET field1 = constant1, field2 = constant2, ...
WHERE id = constid

(हम आईडी द्वारा पहचानी गई वस्तुओं के क्षेत्रों को अधिलेखित कर रहे हैं।) मान एक बाहरी डेटा स्रोत से आते हैं (तालिका में पहले से ही डीबी में नहीं)।

तालिकाओं में मुट्ठी भर सूचकांक हैं और कोई भी विदेशी कुंजी बाधा नहीं है। अंत तक कोई COMMIT नहीं किया जाता है।

pg_dumpपूरे DB के आयात में 2h लगता है । यह एक आधार रेखा की तरह प्रतीत होता है जिसे हमें उचित रूप से लक्षित करना चाहिए।

किसी कस्टम प्रोग्राम के निर्माण की कमी, जो किसी तरह पोस्टग्रेएसक्यूएल के डेटा सेट को फिर से आयात करने के लिए फिर से तैयार करता है, क्या हम कुछ भी कर सकते हैं जो थोक यूपीडेट प्रदर्शन को आयात के करीब ला सकता है? (यह एक ऐसा क्षेत्र है जो हम मानते हैं कि लॉग-स्ट्रक्चर्ड मर्ज ट्री अच्छी तरह से संभालते हैं, लेकिन हम सोच रहे हैं कि क्या ऐसा कुछ है जो हम GggSQL के भीतर कर सकते हैं।)

कुछ विचार:

  • सभी गैर-आईडी सूचकांकों को छोड़ना और बाद में पुनर्निर्माण करना?
  • बढ़ती चेकपॉइंट_सेक्शन, लेकिन क्या यह वास्तव में निरंतर दीर्घकालिक थ्रूपुट में मदद करता है?
  • यहाँ उल्लिखित तकनीकों का उपयोग करना ? (नए डेटा को तालिका के रूप में लोड करें, फिर "पुराने डेटा में विलय करें" जहां आईडी नए डेटा में नहीं मिली है)

मूल रूप से कोशिश करने के लिए चीजों का एक समूह है और हमें यकीन नहीं है कि सबसे प्रभावी क्या हैं या अगर हम अन्य चीजों की अनदेखी कर रहे हैं। हम अगले कुछ दिन प्रयोग करने में बिताएंगे, लेकिन हमने सोचा कि हम यहाँ भी पूछेंगे।

मेरे पास टेबल पर समवर्ती भार है लेकिन यह केवल पढ़ने के लिए है।


आपके प्रश्न में महत्वपूर्ण जानकारी गायब है: Postgres का आपका संस्करण? मूल्य कहां से आते हैं? डेटाबेस के बाहर एक फ़ाइल की तरह लगता है, लेकिन कृपया स्पष्ट करें। क्या आपके पास लक्ष्य तालिका पर समवर्ती भार है? यदि हाँ, तो क्या? या आप ड्रॉप और रीक्रिएट कर सकते हैं? कोई विदेशी कुंजी नहीं, ठीक है - लेकिन क्या विचारों जैसी वस्तुओं के आधार पर अन्य हैं? कृपया लापता जानकारी के साथ अपने प्रश्न को संपादित करें। एक टिप्पणी में इसे निचोड़ मत करो।
इरविन ब्रान्डेसटेटर

@ErwinBrandstetter धन्यवाद, मेरे प्रश्न को अपडेट किया।
यांग

मुझे लगता है कि आपने इसके माध्यम से जाँच की है explain analyzeकि यह लुकअप के लिए एक सूचकांक का उपयोग कर रहा है?
रोजरपैक

जवाबों:


45

मान्यताओं

चूँकि जानकारी Q में गुम है, इसलिए मैं मान लूंगा:

  • आपका डेटा डेटाबेस सर्वर पर एक फ़ाइल से आता है।
  • लक्ष्य तालिका से मिलान करने के लिए COPYएक अद्वितीय id प्रति पंक्ति के साथ डेटा को आउटपुट की तरह स्वरूपित किया जाता है ।
    यदि नहीं, तो इसे पहले ठीक से प्रारूपित COPYकरें या प्रारूप से निपटने के लिए विकल्पों का उपयोग करें।
  • आप लक्ष्य तालिका या उनमें से प्रत्येक में हर एक पंक्ति को अपडेट कर रहे हैं।
  • आप लक्ष्य तालिका को गिराने और फिर से बनाने का जोखिम उठा सकते हैं।
    इसका मतलब है कि कोई समवर्ती पहुंच नहीं है। इससे संबंधित उत्तर पर विचार करें:
  • सूचकांकों को छोड़कर, सभी वस्तुओं पर निर्भर नहीं हैं।

समाधान

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

अस्थायी तालिका बनाने के लिए, एक सरल और तेज़ तरीका है:

CREATE TEMP TABLE tmp_tbl AS SELECT * FROM tbl LIMIT 0;

डेटाबेस के अंदरUPDATE एक अस्थायी तालिका से एक बड़ा बड़ा परिमाण के कई आदेशों द्वारा डेटाबेस के बाहर से व्यक्तिगत अपडेट की तुलना में तेज़ होगा।

में PostgreSQL के MVCC मॉडल , एक UPDATEसाधन एक नई पंक्ति संस्करण बना सकते हैं और के रूप में नष्ट पुराने एक चिह्नित करने के लिए। यह एक INSERTऔर एक DELETEसंयुक्त रूप में महंगा है । साथ ही, यह आपको बहुत सारे मृत ट्यूपल्स के साथ छोड़ देता है। चूंकि आप पूरी तालिका को वैसे भी अपडेट कर रहे हैं, इसलिए यह केवल एक नई तालिका बनाने और पुराने को छोड़ने के लिए समग्र रूप से तेज़ होगा।

यदि आपके पास पर्याप्त रैम उपलब्ध है, तो सेट करें temp_buffers(केवल इस सत्र के लिए!) रैम में अस्थायी तालिका रखने के लिए पर्याप्त - इससे पहले कि आप कुछ और करें।

यह अनुमान लगाने के लिए कि RAM की कितनी आवश्यकता है, एक छोटे नमूने के साथ एक परीक्षण चलाएं और db ऑब्जेक्ट आकार के कार्यों का उपयोग करें :

SELECT pg_size_pretty(pg_relation_size('tmp_tbl'));  -- complete size of table
SELECT pg_column_size(t) FROM tmp_tbl t LIMIT 10;  -- size of sample rows

पूरी स्क्रिप्ट

SET temp_buffers = '1GB';        -- example value

CREATE TEMP TABLE tmp_tbl AS SELECT * FROM tbl LIMIT 0;

COPY tmp_tbl FROM '/absolute/path/to/file';

CREATE TABLE tbl_new AS
SELECT t.col1, t.col2, u.field1, u.field2
FROM   tbl     t
JOIN   tmp_tbl u USING (id);

-- Create indexes like in original table
ALTER TABLE tbl_new ADD PRIMARY KEY ...;
CREATE INDEX ... ON tbl_new (...);
CREATE INDEX ... ON tbl_new (...);

-- exclusive lock on tbl for a very brief time window!
DROP TABLE tbl;
ALTER TABLE tbl_new RENAME TO tbl;

DROP TABLE tmp_tbl; -- will also be dropped at end of session automatically

समवर्ती भार

तालिका पर समवर्ती संचालन (जिसे मैंने शुरू में मान्यताओं में खारिज कर दिया था) प्रतीक्षा करेगा, एक बार तालिका अंत के पास बंद कर दी जाती है और लेनदेन के प्रतिबद्ध होते ही विफल हो जाती है, क्योंकि तालिका का नाम इसके ओआईडी के तुरंत हल हो जाता है, लेकिन नई तालिका में एक अलग OID है। तालिका सुसंगत रहती है, लेकिन समवर्ती संचालन को एक अपवाद मिल सकता है और दोहराया जाना चाहिए। इस संबंधित उत्तर में विवरण:

अद्यतन मार्ग

यदि आपको () को UPDATEरूट जाना है , तो अपडेट के दौरान आवश्यक किसी भी इंडेक्स को न छोड़ें और बाद में इसे फिर से बनाएं। यह एक टुकड़ा बनाने के लिए प्रत्येक व्यक्तिगत पंक्ति के लिए अद्यतन करने की तुलना में बहुत सस्ता है। यह HOT अपडेट के लिए भी अनुमति दे सकता है ।

मैं का उपयोग कर एक समान प्रक्रिया उल्लिखित UPDATEमें इतने पर इस करीबी उत्तर

 


1
मैं वास्तव में लक्ष्य तालिका में केवल 20% पंक्तियों को अपडेट कर रहा हूं - सभी नहीं, लेकिन एक बड़ा पर्याप्त हिस्सा जो कि मर्ज शायद यादृच्छिक अपडेट की तुलना में बेहतर है।
यांग

1
@AryehLeibTaurog: यह तब से नहीं हो रहा है जब DROP TABLEसे एक बाहर ले जाता है Access Exclusive Lock। किसी भी तरह से, मैंने पहले से ही अपने उत्तर के शीर्ष पर पहले से ही सूचीबद्ध किया है: You can afford to drop and recreate the target table.यह लेनदेन की शुरुआत में तालिका को बंद करने में मदद कर सकता है। मेरा सुझाव है कि आप अपनी स्थिति के सभी प्रासंगिक विवरणों के साथ एक नया प्रश्न शुरू करें ताकि हम इस की तह तक पहुँच सकें।
इरविन ब्रान्डेसटेटर

1
@ErwinBrandstetter दिलचस्प। यह सर्वर संस्करण पर निर्भर करता है। मैंने psycopg2 एडॉप्टर का उपयोग करके psql क्लाइंट का उपयोग करके 8.4 और 9.1 पर त्रुटि को पुन: उत्पन्न किया है । 9.3 पर कोई त्रुटि नहीं है। पहली स्क्रिप्ट में मेरी टिप्पणी देखें। मुझे यकीन नहीं है कि अगर यहां पोस्ट करने का सवाल है, लेकिन यह पोस्टग्रैसक्ल सूचियों में से किसी एक पर कुछ जानकारी की मांग के लायक हो सकता है।
आर्येह लीब तौआरोग

1
मैंने प्रक्रिया को स्वचालित करने के लिए अजगर में एक साधारण सहायक वर्ग लिखा ।
आर्येह लीब तौआरोग

3
बहुत उपयोगी जवाब। थोड़े बदलाव के रूप में, कोई केवल अद्यतन किए जाने वाले स्तंभ और संदर्भ के कॉलम के साथ अस्थायी तालिका बना सकता है, मूल तालिका से अपडेट किए जाने वाले कॉलम हटाएं, फिर तालिकाओं का उपयोग करके विलय कर सकते हैं, जिसके लिए पंक्तियों को रखने CREATE TABLE tbl_new AS SELECT t.*, u.field1, u.field2 from tbl t NATURAL LEFT JOIN tmp_tbl u;की LEFT JOINअनुमति है, जिसके लिए कोई अद्यतन नहीं है। बेशक NATURALकिसी भी मान्य USING()या में बदला जा सकता है ON
स्किप्पी ले ग्रैंड गौरौ

2

यदि डेटा एक संरचित फ़ाइल में उपलब्ध कराया जा सकता है, तो आप इसे एक विदेशी डेटा आवरण के साथ पढ़ सकते हैं और लक्ष्य तालिका पर मर्ज कर सकते हैं ।


3
"विशेष रूप से लक्ष्य तालिका में विलय" से आपका क्या मतलब है? FDW का उपयोग एक अस्थायी तालिका में कॉपी करने से बेहतर क्यों है (जैसा कि मूल प्रश्न में तीसरी बुलेट में सुझाव दिया गया है)?
यांग

MERGE sql स्टेटमेंट में "मर्ज" करें। एफडीडब्ल्यू का उपयोग करने से आप एक अस्थायी तालिका में डेटा की प्रतिलिपि बनाने के अतिरिक्त चरण के बिना कर सकते हैं। मैं यह मान रहा हूं कि आप पूरे डेटा सेट को प्रतिस्थापित नहीं कर रहे हैं, और यह है कि फ़ाइल में एक निश्चित मात्रा में डेटा होगा जो वर्तमान डेटा सेट से परिवर्तन का प्रतिनिधित्व नहीं करेगा - यदि एक महत्वपूर्ण राशि बदल गई है तो एक पूर्ण तालिका का प्रतिस्थापन सार्थक हो सकता है।
डेविड एल्ड्रिज

1
@DavidAldridge: SQL: 2003 मानक में परिभाषित करते हुए, MERGEPostgreSQL (अभी तक) में लागू नहीं किया गया है । अन्य RDBMS में कार्यान्वयन काफी भिन्न होता है। के लिए टैग जानकारी पर विचार करें MERGEऔर UPSERT
एरविन ब्रान्डेसटेटर

@ErwinBrandstetter [glurk] ओह हां काफी। वेल मर्ज केक पर आइसिंग है वास्तव में मुझे लगता है। आयात-से-अस्थायी-टेबल-स्टेप के बिना डेटा तक पहुंचना वास्तव में एफडीडब्ल्यू तकनीक का चरम है।
डेविड एल्ड्रिज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.