2010-06-04 14 views
9

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

start a transaction with serializable isolation level; 
INSERT INTO dest_table SELECT data FROM orig_table,other-tables WHERE <condition>; 
DELETE FROM orig_table USING other-tables WHERE <condition>; 
COMMIT; 

अब क्या डेटा की मात्रा नहीं बल्कि बड़ा है, और <condition> गणना करने के लिए महंगा है तो क्या होगा? PostgreSQL में, एक RULE या संग्रहीत प्रक्रिया का उपयोग फ्लाई पर डेटा हटाने के लिए किया जा सकता है, केवल एक बार स्थिति का मूल्यांकन किया जा सकता है। कौन सा समाधान बेहतर है? क्या अन्य विकल्प हैं?

उत्तर

0

आपने किसी फ़ाइल का तालिका डेटा डंप सकता है, तो का उपयोग कर COPY आमतौर पर COPYINSERT की तुलना में तेजी है एक और मेज पर डालें।

+1

मैं कुछ परीक्षण प्रसंस्करण कर दिया है ट्रिगर का उपयोग करके डेटा की बड़ी मात्रा, पंक्ति से पंक्ति, और एक लेनदेन के साथ एक संग्रहीत प्रक्रिया का उपयोग करना। संग्रहित प्रक्रिया दृष्टिकोण तेज़ था। – pcent

+0

आपको प्रदर्शन को बढ़ाने के लिए अपने PostgreSQL सर्वर को भी ठीक करना चाहिए। पढ़ें: http://wiki.postgresql.org/wiki/Performance_Optimization – pcent

+0

याह, मुझे लगता है कि दिशानिर्देश यह कहने के लिए योग्य होना चाहिए कि एक प्रति व्यक्ति INSERT कथन के एक सेट से तेज है, प्रति पंक्ति एक। INSERT ... डेटा को कॉपी करने के लिए चुनें, मुझे लगता है कि निष्पादक के बाहर डेटा पारित नहीं किया जा रहा है क्योंकि मुझे लगता है कि इष्टतम था। – araqnid

7

यदि स्थिति इतनी जटिल है कि आप इसे दो बार निष्पादित नहीं करना चाहते हैं (जो कि बीटीडब्ल्यू मेरे लिए असंभव लगता है, लेकिन वैसे भी), एक संभावना है कि मूल तालिका पर ALTER TABLE ... ADD COLUMN एक बूलियन फ़ील्ड जोड़ने और चलाने के लिए उस फ़ील्ड को सही WHERE <condition> पर सेट करने के लिए तालिका पर UPDATE। फिर आपके INSERT और DELETE आदेश आसानी से इस कॉलम को उनके WHERE खंडों के लिए देख सकते हैं।

बाद में स्रोत और गंतव्य सारणी दोनों से कॉलम को मिटाना न भूलें!

हम्म, यहां तक ​​कि कम घुसपैठ करने वाला एक नया अस्थायी तालिका बनाना होगा जिसका एकमात्र उद्देश्य उन रिकॉर्ड्स के पीके को शामिल करना है जिन्हें आप शामिल करना चाहते हैं। इस तालिका में पहले INSERT पंक्तियों के सेट को "परिभाषित" करने के लिए चालू करने के लिए, और उसके बाद टेबल-प्रतिलिपि INSERT और DELETE के लिए इस तालिका के साथ जुड़ें। टेबल पीके अनुक्रमित होने के बाद से ये जुड़ेंगे तेज़ होंगे।


[संपादित करें] टिप्पणी में स्कॉट बेली सुझाव स्पष्ट रूप से यह करने के लिए सही तरीका है, इच्छा मैं अपने आप को इसके बारे में सोचा था! मान लें कि सभी मूल तालिका के पीके फ़ील्ड गंतव्य तालिका में मौजूद होंगे, अस्थायी तालिका की आवश्यकता नहीं है - गंतव्य में सम्मिलित करने के लिए जटिल WHERE स्थितियों का उपयोग करें, फिर इस तालिका में शामिल होने से मूल तालिका से DELETE। मैं अब एक अलग टेबल का सुझाव देने के लिए बेवकूफ महसूस करता हूँ! :)

+0

अस्थायी तालिका मेरा वोट प्राप्त करती है। पंक्तियों को अद्यतन करना और फिर उन्हें हटाने का मतलब ढेर में बहुत सारे कचरे का निर्माण करना है, साथ ही तालिका स्कीमा को छूने की आवश्यकता है (यह वास्तव में महत्वपूर्ण नहीं है) – araqnid

+0

पीके के लिए अस्थायी तालिका के लिए +1। – rfusca

+4

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

6

आप Postgres 9.1 में एक क्वेरी का उपयोग कर डेटा स्थानांतरित कर सकते हैं http://www.postgresql.org/docs/9.1/static/queries-with.html धारा "डेटा-के संशोधन में बयान" देखें

+0

मैंने इसे चेक किया, यह डालने से धीमा था + हटाएं – Christian

24

आप एक मौजूदा करने के लिए स्थानांतरित कर सकते हैं

[dvv's answer पर विस्तार] निम्नानुसार तालिका। बेजोड़ स्कीमा के लिए, आपको कॉलम निर्दिष्ट करना चाहिए।

WITH moved_rows AS (
    DELETE FROM <original_table> a 
    USING <other_table> b 
    WHERE <condition> 
    RETURNING a.* -- or specify columns 
) 
INSERT INTO <existing_table> --specify columns if necessary 
SELECT [DISTINCT] * FROM moved_rows; 

लेकिन अगर आप एक नई तालिका (नहीं एक मौजूदा एक) में डेटा ले जाना चाहते हैं, बाहरी वाक्य रचना अलग है:

CREATE TABLE <new_table> AS 
WITH moved_rows AS (
    DELETE FROM <original_table> a 
    USING <other_table> b 
    WHERE <condition> 
    RETURNING a.* -- or specify columns 
) 
SELECT [DISTINCT] * FROM moved_rows; 
संबंधित मुद्दे