2012-09-19 10 views
5

में रिकॉर्ड बदल गया है या नहीं, यह कैसे बताना है कि मेरे पास "अपरर्ट" प्रकार का प्रश्न है ... लेकिन, मैं इसे वहां फेंकना चाहता हूं क्योंकि यह किसी भी चीज़ से थोड़ा अलग है जिसे मैंने पढ़ा है स्टैक ओवरफ़्लो।पोस्टग्रेज़

मूल समस्या।

मैं mysql से PostgreSQL 9.1.5 (Heroku पर होस्ट किया गया) से आगे बढ़ने पर काम कर रहा हूं। इसके एक हिस्से के रूप में, मुझे प्रतिदिन कई सीएसवी फाइलों को आयात करने की आवश्यकता है। कुछ डेटा बिक्री की जानकारी है और लगभग नए होने की गारंटी है और इसे सम्मिलित करने की आवश्यकता है। लेकिन, डेटा के अन्य हिस्सों को लगभग समान होने की गारंटी है। उदाहरण के लिए, सीएसवी फाइलें (नोट बहुवचन) में पीओएस (बिक्री का बिंदु) जानकारी होगी। यह शायद ही कभी बदलता है (और केवल जोड़ों के माध्यम से सबसे अधिक संभावना है)। फिर उत्पाद की जानकारी है। लगभग 10,000 उत्पाद हैं (विशाल बहुमत अपरिवर्तित होगा, लेकिन दोनों जोड़ों और अपडेटों के लिए संभव है)।

अंतिम आइटम (लेकिन महत्वपूर्ण है), यह है कि मुझे किसी दिए गए आइटम के लिए ऑडिट ट्रेल/जानकारी प्रदान करने में सक्षम होना आवश्यक है। उदाहरण के लिए, यदि मैं एक नया पीओएस रिकॉर्ड जोड़ता हूं, तो मुझे उस फाइल को वापस उस फ़ाइल में ढूंढने में सक्षम होना चाहिए। अगर मैं यूपीसी कोड या किसी उत्पाद का वर्णन बदलता हूं, तो मुझे इसे वापस ढूंढने में सक्षम होना चाहिए आयात (और फ़ाइल) जहां परिवर्तन आया था।

समाधान जो मैं सोच रहा हूं।

चूंकि डेटा सीएसवी के माध्यम से मुझे प्रदान किया जाता है, तो मैं इस विचार के आसपास काम कर रहा हूं कि सीओपीवाई सबसे अच्छा/सबसे तेज़ तरीका होगा। फ़ाइलों में डेटा की संरचना बिल्कुल मेरे पास डेटाबेस में नहीं है (यानी अंतिम गंतव्य)। इसलिए, मैं उन्हें स्टेज स्कीमा में टेबल में कॉपी कर रहा हूं जो सीएसवी से मेल खाते हैं (नोट: प्रति स्तरीय डेटासेट)। स्टेजिंग स्कीमा में टेबल में पहले से सम्मिलित पंक्ति ट्रिगर्स होंगे। ये ट्रिगर्स तय कर सकते हैं कि डेटा के साथ क्या करना है (डालें, अपडेट करें या अनदेखा करें)।

उन तालिकाओं के लिए जिनके पास नए डेटा होने की संभावना है, तो यह पहले डालने का प्रयास करेगा। यदि रिकॉर्ड पहले से मौजूद है, तो यह न्यूल लौटाएगा (और स्टेजिंग टेबल में डालने को रोक देगा)। उन तालिकाओं के लिए जो शायद ही कभी बदलते हैं, फिर यह तालिका से पूछेगा और देखें कि रिकॉर्ड मिला है या नहीं। यदि ऐसा है, तो मुझे यह देखने का एक तरीका चाहिए कि कोई भी फ़ील्ड बदल गया है या नहीं। (क्योंकि याद रखें, मुझे यह दिखाने की ज़रूरत है कि रिकॉर्ड वाई से आयात एक्स द्वारा संशोधित किया गया था) मैं स्पष्ट रूप से कोड को बॉयलर प्लेट से बाहर कर सकता हूं और प्रत्येक कॉलम का परीक्षण कर सकता हूं। लेकिन, कुछ और अधिक "वाक्प्रचार" और उस से अधिक रखरखाव की तलाश में था।

एक तरह से, मैं जो कर रहा हूं वह एक ऑडिट ट्रेल सिस्टम के साथ एक आयात प्रणाली का संयोजन कर रहा है। इसलिए, ऑडिट ट्रेल्स की खोज में, मैंने निम्नलिखित wiki.postgresql.org आलेख की समीक्षा की। ऐसा लगता है कि हिस्टोर परिवर्तन प्राप्त करने का एक अच्छा तरीका हो सकता है (और तालिका में कुछ स्तंभों को आसानी से अनदेखा करने में सक्षम होना जो महत्वपूर्ण नहीं हैं - उदाहरण के लिए "last_modified")

मुझे लगभग 9 0% यकीन है कि यह सब होगा काम ... मैंने कुछ परीक्षण टेबल बनाए हैं और इसके साथ खेला है।

मेरा प्रश्न?

10K में से 3 रिकॉर्ड प्राप्त करने के इस कार्य को पूरा करने का एक बेहतर, अधिक रखरखाव तरीका है जिसके लिए डेटाबेस में परिवर्तन की आवश्यकता है। मैं निश्चित रूप से एक पायथन लिपि (या कुछ और) लिख सकता हूं जो फ़ाइल को पढ़ता है और यह पता लगाने की कोशिश करता है कि प्रत्येक रिकॉर्ड के साथ क्या करना है, लेकिन यह बहुत अक्षम है और इससे कई दौर यात्राएं होती हैं।

कुछ अंतिम बातें:

  1. मैं इनपुट फ़ाइलों पर नियंत्रण नहीं है। अगर मैं केवल मुझे डेल्टा भेजता हूं, तो मैं इसे प्यार करता हूं, लेकिन वे नहीं करते हैं और यह पूरी तरह से मेरे नियंत्रण या प्रभाव से बाहर है।
  2. वह सिस्टम बढ़ता जा रहा है और नए डेटा स्रोतों को जोड़ने की संभावना है जो संसाधित किए जा रहे डेटा की मात्रा में काफी वृद्धि करेगा (इसलिए, मैं चीजों को कुशल रखने की कोशिश कर रहा हूं)
  3. मुझे पता है कि यह अच्छा नहीं है, सरल प्रश्न (जैसे "पायथन में एक सूची को कैसे क्रमबद्ध करें") लेकिन मुझे विश्वास है कि एसओ के बारे में महान चीजों में से एक यह है कि आप कड़ी प्रश्न पूछ सकते हैं और लोग अपने विचारों को साझा करेंगे कि वे इसे हल करने का सबसे अच्छा तरीका कैसे सोचते हैं।
+0

दो (अंतिम) प्रश्न: 1) क्या आपके पास हटाना है, या इनपुट "incremental" है? 2) डेटा गारंटी के आपूर्तिकर्ताओं * स्थिर कुंजी * (कोई महत्वपूर्ण अपडेट) कर सकते हैं? – wildplasser

+0

यह डेटा स्रोत और डेटा के प्रकार के साथ विभिन्न है। यह निश्चित रूप से एक ऐसी स्थिति है जहां डेटा को संभालने के दौरान मुझे शायद "रक्षात्मक" होना चाहिए और कुछ भी के लिए तैयार रहना चाहिए।उस ने कहा, मुझे लगता है कि मैं हटा सकता था (लेकिन, दुर्लभ) और मुझे विश्वास है कि कुंजी * स्थिर होना चाहिए (दूसरे शब्दों में, पीओएस रिकॉर्ड के लिए आईडी अपलोड के बीच समान रहना चाहिए)। –

उत्तर

7

मेरे पास बहुत सारे समान ऑपरेशन हैं। - अस्थायी

CREATE TEMP TABLE target_tmp AS 
SELECT * FROM target_tbl LIMIT 0; -- only copy structure, no data 

COPY target_tmp FROM '/path/to/target.csv'; 

के लिए प्रदर्शन, ANALYZE चलाएँ: मुझे क्या COPYके लिए अस्थायी मचान तालिकाओं है। autovacuum द्वारा टेबल का विश्लेषण नहीं किया जाता है!

ANALYZE target_tmp; 

प्रदर्शन के लिए भी, शायद टेम्पलेट तालिका पर एक इंडेक्स या दो भी बना सकते हैं, या डेटा प्राथमिकता जोड़ने पर प्राथमिक कुंजी जोड़ सकते हैं।

ALTER TABLE ADD CONSTRAINT target_tmp_pkey PRIMARY KEY(target_id); 

आपको छोटे आयात के लिए प्रदर्शन सामग्री की आवश्यकता नहीं है।

फिर नए डेटा को पचाने के लिए SQL कमांड के पूर्ण दायरे का उपयोग करें।
उदाहरण के लिए, यदि लक्ष्य तालिका की प्राथमिक कुंजी target_id है ..

शायद DELETE क्या वहाँ नहीं है किसी भी अधिक?

DELETE FROM target_tbl t 
WHERE NOT EXISTS (
    SELECT 1 FROM target_tmp t1 
    WHERE t1.target_id = t.target_id 
); 

फिर UPDATE क्या पहले से ही वहाँ है:

UPDATE target_tbl t 
SET col1 = t1.col1 
FROM target_tmp t1 
WHERE t.target_id = t1.target_id 

खाली के अपडेट से बचने के लिए, बस जोड़ें:

... 
AND col1 IS DISTINCT FROM t1.col1; -- repeat for relevant columns 

या, अगर पूरी पंक्ति प्रासंगिक है:

... 
AND t IS DISTINCT FROM t1;   -- check the whole row 
फिर

INSERT नया क्या है:

INSERT INTO target_tbl(target_id, col1) 
SELECT t1.target_id, t1.col1 
FROM target_tmp t1 
LEFT JOIN target_tbl t USING (target_id) 
WHERE t.target_id IS NULL; 

स्वच्छ ऊपर अपने सत्र (अस्थायी तालिकाओं सत्र के अंत में स्वचालित रूप से हटा दिया जाता है) पर चला जाता है, तो:

DROP TABLE target_tmp; 

या ON COMMIT DROP या इसी तरह का उपयोग के साथ CREATE TEMP TABLE
कोड अनचाहे, लेकिन टाइपोज़ को छोड़कर PostgreSQL के किसी भी आधुनिक संस्करण में काम करना चाहिए।

+0

उत्तर के लिए धन्यवाद। अच्छा उदाहरण/विवरण; मुझे यकीन है कि यह कुछ लोगों की मदद करेगा। और यह बहुत करीब है जो मुझे करने की ज़रूरत है। मुझे प्राप्त करने की एक आवश्यकता यह है कि "बैच आईडी" आयात का ट्रैक ट्रैक वास्तव में रिकॉर्ड बदल गया है। दूसरे शब्दों में, यदि मैं मौजूद हूं तो रिकॉर्ड हमेशा सही/रीफ्रेश नहीं करना चाहता - केवल परिवर्तन होने पर अपडेट करें। मुझे लगता है कि मैं कर सकता था। और उसके बाद बस टेबल पर एक अपडेट ट्रिगर है और अगर रिकॉर्ड वास्तव में बदल गया है तो वहां पता लगाएं ... यदि हां, तो ऑडिट ट्रेल रिकॉर्ड जोड़ें। उचित लगता है? एक बेहतर तरीका मिला? –

+0

@ डेविड: यह आपकी अपेक्षा से आसान हो सकता है। मैंने अद्यतन अनुभाग में थोड़ा सा जोड़ा। वैसे भी रिक्त अपडेट को बाहर करना हमेशा एक अच्छा विचार है। यदि आपको ऑडिट ट्रेल की आवश्यकता है, तो मैं सुझाव दूंगा कि आप 'हटाएं'/'अपडेट करें 'से पहले पुराने संस्करण (प्लस टाइमस्टैंप) को इतिहास तालिका में कॉपी करें। –

+0

अच्छे सुझाव और उत्तर को अपडेट करने के लिए धन्यवाद। ऑडिटिंग उद्देश्यों के लिए, क्या आप केवल hstore (x। *) का उपयोग करके संग्रह तालिका (डेटा + टाइमस्टैम्प की एक पूर्ण प्रति) पर प्रतिलिपि बनाना पसंद करते हैं और इसे ऑडिट_ट्रिल/इतिहास प्रकार तालिका में टेक्स्ट फ़ील्ड में संग्रहीत करते हैं? संग्रह तालिका का मुख्य लाभ यह है कि यह आसानी से पूछताछ की जाती है। यदि आपकी स्कीमा सड़क पर बदल जाती है तो हैस्टोर दृष्टिकोण का मुख्य लाभ लचीलापन लगता है। मुझे पता है कि यह थोड़ा सा विषय है और शायद यह स्वयं का सवाल हो सकता है, लेकिन आपके विचारों के लिए उत्सुक है। धन्यवाद! –