Postgresql में एक तालिका से दूसरी पंक्ति में लाखों पंक्तियों को कुशलता से कैसे कॉपी करें?


37

मेरे पास दो डेटाबेस टेबल हैं। एक में करोड़ों के रिकॉर्ड होते हैं। चलो उस एक को बुलाओ history। दूसरे की गणना दैनिक आधार पर की जाती है और मैं इसके सभी रिकॉर्ड historyएक में कॉपी करना चाहता हूं ।

मैंने क्या किया था:

INSERT INTO history SELECT * FROM daily

और इसने थोड़ी देर के लिए चाल चली, लेकिन यह धीमी और धीमी होने लगी क्योंकि रिकॉर्ड की संख्या बढ़ती रही। अब मैं लगभग 2 मिलियन रिकॉर्ड से नकल करने की आवश्यकता है है dailyकरने के लिए historyएक ऑपरेशन में है और इसे पूरा करने के लिए बहुत समय लगता है।

क्या एक तालिका से दूसरी तालिका में डेटा की प्रतिलिपि बनाने का एक और अधिक कुशल तरीका है?

जवाबों:


10

यदि आप लंबे समय (कई महीनों) के लिए इतिहास रखने की योजना बनाते हैं, तो मेरा सुझाव है कि विभाजन विकल्पों पर एक नज़र डालें - प्रत्येक दिन या सप्ताह और इसी तरह एक विभाजन हो सकता है। यह आप की हिस्ट्री टेबल के एक्सेस पैटर्न पर भी निर्भर करता है (क्या आप ऐसे प्रश्नों को चलाते हैं जो डेट्स पर डेटा एक्सेस करते हैं? क्या आप बहुत सारे एग्रीगेट आदि करते हैं)। समुच्चय / सारांश के भंडारण के लिए भौतिक विचारों पर एक नज़र है। http://www.postgresql.org/docs/9.3/static/ddl-partitioning.html http://www.postgresql.org/docs/9.3/static/sql-creatematerializedview.html


जवाब के लिए धन्यवाद। यह जाने का एकमात्र तरीका लगता है। मुझे महीनों तक डेटा को विभाजित करने की आवश्यकता है और इस प्रकार रीइन्डेक्सिंग करना (चूंकि इंडेक्स पुनर्जनन एक समस्या थी यहां) बहुत तेजी से।
मिल्वान जोगोविक

16

सीएसवी प्रारूप में तालिका को डंप करें

COPY table TO '/tmp/table.csv' DELIMITER ',';

COPY कमांड का उपयोग करें जो बड़ी मात्रा में डेटा के लिए कहीं अधिक कुशल है।

COPY table FROM '/tmp/table.csv' DELIMITER ',';

अधिक जानकारी के लिए http://www.postgresql.org/docs/current/static/sql-copy.html पर पोस्ट डॉक्स देखें


1
यह अभी भी बहुत, बहुत धीमी गति से चल रहा है ... शायद यह इतना बड़ा सूचकांक के पुनर्निर्माण के साथ कुछ करना है? historyतालिका में 160 मिलियन पंक्तियाँ हैं , और हम 3 और मिलियन पंक्तियों को जोड़ रहे हैं।
मिल्वान ज़ोगोविक

2
आप में से एक खाली टेबल फुल कर रहे हैं, या पहले से मौजूद अधिक पंक्तियों को जोड़ रहे हैं, यह आमतौर पर गैर-संकुलित अनुक्रमित को छोड़ने और स्थानांतरण पूरा होने तक उन्हें फिर से बनाना अधिक कुशल है (जब तक कि तालिका का सक्रिय उपयोग न हो) )
डेविड स्पिल्ट

BTW, क्या यह एक बंद ऑपरेशन है या यह कुछ ऐसा है जो आपको नियमित रूप से करना है? यदि इसका नियमित आधार पर मैं सफल होता हूं कि आप एक ट्रिगर बनाते हैं तो आपको हर बार इस परीक्षा से गुजरना नहीं पड़ता है।
फबरीज़ियो माज़ोनी

@FabrizioMazzoni - यह विशिष्ट समय पर दैनिक आधार पर किया जाना है (थोड़े समय में स्नैपशॉट ले रहा है)।
मिलोवैन ज़ोगोविक

@DavidSpillett - वास्तव में! ड्रॉपिंग इंडेक्स बहुत तेजी से आयात करता है (ऊपर मेरा उत्तर देखें), हालाँकि, इंडेक्स को फिर से बनाने में घंटों लगते हैं (क्योंकि मेरे पास डेटाबेस में 160M पंक्तियाँ हैं ..)
मिलोवैन ज़ोगोविक

14

समस्या सूचकांक के साथ थी। historyतालिका 160 मी अनुक्रमित पंक्तियों था। COPY FROMया तो चलने से या INSERT INTO .. SELECTपंक्तियों को सम्मिलित करने में नहीं बल्कि अनुक्रमणिका को अपडेट करने में बहुत समय लग रहा था। जब मैंने इंडेक्स को अक्षम किया, तो उसने 10 सेकंड में 3M पंक्तियों को आयात किया। अब मुझे बड़ी तालिका को फिर से बनाने का तेज़ तरीका खोजने की आवश्यकता है।


3
क्या आपको इतिहास की मेज पर अनुक्रमित करने की भी आवश्यकता है?
शर्लक

2
सूचकांक समवर्ती कीवर्ड का उपयोग करें
Akvel

10

आप psql टूल का उपयोग कर सकते हैं , मैं निम्नलिखित के रूप में कुशल हो सकता है,

psql -h ${DAILY_HOST_IP} -p ${PG_PORT} ${DB_NAME} ${USER_NAME} -c "copy daily to stdout " | psql -h ${HISTORY_HOST_IP} -p ${PG_PORT} ${DB_NAME} ${USER_NAME}  -c "copy history from stdin"

इसके अलावा आप एक शेल स्क्रिप्ट लिख सकते हैं।


मध्यवर्ती फ़ाइल के बिना महान समाधान। बहुत तेजी से, मैंने नियमित डिस्क और नेटवर्क फ़ाइल सिस्टम के बीच 1h20 (बिना अनुक्रमित के) में 950 मिलियन पंक्तियों की तालिका की प्रतिलिपि बनाई।
ले

3

यह निश्चित रूप से आपके प्रश्न का सटीक उत्तर नहीं है, लेकिन यदि आपको historyतालिका तक पहुंचने की आवश्यकता नहीं है , तो आप SQL डंप भी उत्पन्न कर सकते हैं:

pg_dump -h host -p port -w -U user db > dump.sql

फिर कोई gitअंतर की गणना करने और इसे कुशलता से संग्रहीत करने के लिए एक उपकरण का उपयोग कर सकता है ।

git add dump.sql
git commit -m "temp dump"
git gc --aggressive

यह उपयोगी है क्योंकि एक डेटाबेस में अधिकांश भाग, हर दिन नहीं बदलेगा। हर दिन के लिए एक पूरी प्रति संग्रहीत करने के बजाय, व्यक्ति दो दिनों के अंतर को स्टोर कर सकता है।

आप एक crontabनौकरी का उपयोग कर सकते हैं जैसे कि डंप हर दिन संसाधित होता है।

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