हमारे पास एक विशिष्ट अनुप्रयोग है जो पोस्टग्रेएसक्यूएल 8.3 को भंडारण बैकएंड के रूप में उपयोग करता है (पायथन और psycopg2 का उपयोग करके)। महत्वपूर्ण सारणी में हम जो ऑपरेशन करते हैं, वे अधिकांश मामलों में आवेषण या अपडेट होते हैं (शायद ही कभी हटाते हैं या चयन करते हैं)।मैं PostgreSQL में ऑपरेशंस को अपडेट/प्रतिस्थापित कैसे कर सकता हूं?
स्वच्छता कारणों से हमने अपना खुद का Data Mapper बनाया है-जैसी परत जो उचित रूप से अच्छी तरह से काम करती है, लेकिन इसमें एक बड़ी बाधा, अद्यतन प्रदर्शन है। बेशक, मैं परिदृश्य को प्रतिस्थापित/प्रतिस्थापित करने की उम्मीद नहीं कर रहा हूं, 'एक खाली तालिका में डालें' के रूप में तेज़ी से, लेकिन थोड़ा करीब होना अच्छा लगेगा।
ध्यान दें कि यह प्रणाली समवर्ती अद्यतन
हम हमेशा एक अद्यतन पर प्रत्येक पंक्तियों के सभी क्षेत्रों की स्थापना की है, जो शब्दावली, जहां मैं अपने परीक्षण में शब्द 'की जगह' का उपयोग में देखा जा सकता से मुक्त है। मैं अब तक हमारे अद्यतन समस्या में दो तरीकों की कोशिश की है:
एक
replace()
प्रक्रिया है कि अद्यतन करने के लिए पंक्तियों की एक सरणी लेता बनाएँ:CREATE OR REPLACE FUNCTION replace_item(data item[]) RETURNS VOID AS $$ BEGIN FOR i IN COALESCE(array_lower(data,1),0) .. COALESCE(array_upper(data,1),-1) LOOP UPDATE item SET a0=data[i].a0,a1=data[i].a1,a2=data[i].a2 WHERE key=data[i].key; END LOOP; END; $$ LANGUAGE plpgsql
एक
insert_or_replace
नियम बनाएं ताकि सब कुछ है, लेकिन कभी नष्ट हो जाता है बहु पंक्ति सम्मिलित करताCREATE RULE "insert_or_replace" AS ON INSERT TO "item" WHERE EXISTS(SELECT 1 FROM item WHERE key=NEW.key) DO INSTEAD (UPDATE item SET a0=NEW.a0,a1=NEW.a1,a2=NEW.a2 WHERE key=NEW.key);
गु ese दोनों अद्यतन एक निष्पक्ष बिट को गति, हालांकि बाद धीमा थोड़ा सम्मिलित करता है:
- सभी परीक्षण डेटाबेस के रूप में एक ही कंप्यूटर पर चलाए जा रहे हैं: परीक्षण चालन के बारे में
Multi-row insert : 50000 items inserted in 1.32 seconds averaging 37807.84 items/s executemany() update : 50000 items updated in 26.67 seconds averaging 1874.57 items/s update_andres : 50000 items updated in 3.84 seconds averaging 13028.51 items/s update_merlin83 (i/d/i) : 50000 items updated in 1.29 seconds averaging 38780.46 items/s update_merlin83 (i/u) : 50000 items updated in 1.24 seconds averaging 40313.28 items/s replace_item() procedure : 50000 items replaced in 3.10 seconds averaging 16151.42 items/s Multi-row insert_or_replace: 50000 items inserted in 2.73 seconds averaging 18296.30 items/s Multi-row insert_or_replace: 50000 items replaced in 2.02 seconds averaging 24729.94 items/s
रैंडम नोट्स रहता है; लोकलहोस्ट से कनेक्ट करना
- 500 आइटमों के बैच में डेटाबेस पर सम्मिलित और अद्यतन लागू होते हैं, प्रत्येक अपने लेनदेन में भेजे जाते हैं (अद्यतन)।
- सभी अद्यतन/प्रतिस्थापन परीक्षण उसी मान का उपयोग करते थे जो पहले से ही डेटाबेस में थे।
- सभी डेटा psycopg2 अनुकूल() फ़ंक्शन का उपयोग करके बच निकला था।
- सभी तालिकाओं छोटा कर दिया और उपयोग करने से पहले वैक्यूम कर रहे हैं (जोड़ा, पिछले रन ही काट-छांट हुआ में)
तालिका इस प्रकार है:
CREATE TABLE item ( key MACADDR PRIMARY KEY, a0 VARCHAR, a1 VARCHAR, a2 VARCHAR )
तो, असली सवाल यह है: मैं ऑपरेशन को थोड़ा सा अद्यतन/प्रतिस्थापित कैसे कर सकता हूं? (मुझे लगता है कि ये निष्कर्ष 'पर्याप्त अच्छे' हो सकते हैं, लेकिन मैं एसओ भीड़ को टैप किए बिना छोड़ना नहीं चाहता :)
कोई भी एक और सुरुचिपूर्ण repl_item(), या सबूत की ओर संकेत करता है कि मेरे परीक्षण पूरी तरह से हैं टूटा हुआ स्वागत है।
यदि आप पुन: पेश करने का प्रयास करना चाहते हैं तो परीक्षण स्क्रिप्ट here उपलब्ध है। हालांकि इसे पहले जांचना याद रखें ... यह वर्क्सफ़ोरमे है, लेकिन ...
आपको डीबी संपादित करने की आवश्यकता होगी।अपने सेटअप के अनुरूप कनेक्ट() लाइन।
संपादित
#postgresql में एन्ड्रेस @ freenode मैं एक एकल क्वेरी अद्यतन के साथ एक और परीक्षण करने के लिए धन्यवाद; एक बहु-पंक्ति सम्मिलन की तरह (उपरोक्त update_andres के रूप में सूचीबद्ध)। (I
UPDATE item
SET a0=i.a0, a1=i.a1, a2=i.a2
FROM (VALUES ('00:00:00:00:00:01', 'v0', 'v1', 'v2'),
('00:00:00:00:00:02', 'v3', 'v4', 'v5'),
...
) AS i(key, a0, a1, a2)
WHERE item.key=i.key::macaddr
संपादित
#postgresql @ नीचे मैं एक डालने करने वाली अस्थायी साथ एक और परीक्षण किया है freenode और सुराही/JWP में merlin83 के लिए धन्यवाद/हटाने/डालने दृष्टिकोण ("के रूप में सूचीबद्ध update_merlin83/डी/i) "ऊपर)।
INSERT INTO temp_item (key, a0, a1, a2)
VALUES (
('00:00:00:00:00:01', 'v0', 'v1', 'v2'),
('00:00:00:00:00:02', 'v3', 'v4', 'v5'),
...);
DELETE FROM item
USING temp_item
WHERE item.key=temp_item.key;
INSERT INTO item (key, a0, a1, a2)
SELECT key, a0, a1, a2
FROM temp_item;
मेरे पेट लग रहा है कि इन परीक्षणों वास्तविक दुनिया परिदृश्य में प्रदर्शन करने के लिए बहुत प्रतिनिधि नहीं हैं, लेकिन मुझे लगता है कि मतभेदों को काफी महान आगे की जांच पड़ताल के लिए सबसे होनहार दृष्टिकोण का एक संकेत देने के लिए कर रहे हैं। Perftest.py स्क्रिप्ट में उन सभी के लिए भी सभी अपडेट शामिल हैं जो इसे देखना चाहते हैं। हालांकि यह काफी बदसूरत है, @ freenode ने बताया कि मैं एक डालने करने वाली अस्थायी/अद्यतन संस्करण के साथ परीक्षण करना चाहिए तो अपने चश्मे :)
संपादित
#postgresql में एन्ड्रेस मत भूलना (के रूप में सूचीबद्ध "ऊपर_merlin83 (i/u)" ऊपर)।
INSERT INTO temp_item (key, a0, a1, a2)
VALUES (
('00:00:00:00:00:01', 'v0', 'v1', 'v2'),
('00:00:00:00:00:02', 'v3', 'v4', 'v5'),
...);
UPDATE item
SET a0=temp_item.a0, a1=temp_item.a1, a2=temp_item.a2
FROM temp_item
WHERE item.key=temp_item.key
संपादित
शायद अंतिम संपादन: मैं अपने स्क्रिप्ट हमारी लोड परिदृश्य बेहतर मिलान करने के लिए बदल गया है, और ऐसा लगता है जब चीजें थोड़ा स्केलिंग और कुछ अनियमितता जोड़ने संख्या भी पकड़ो। अगर किसी को किसी अन्य परिदृश्य से बहुत अलग संख्या मिलती है तो मुझे इसके बारे में जानने में दिलचस्पी होगी।
कैसे प्रासंगिक तालिकाओं में अनुक्रमित रहे हैं? कोई विदेशी केई? –
परीक्षण-स्क्रिप्ट में नहीं, नहीं। असली दुनिया में, एक। –
क्या आप अपने 'अपडेट' के 'एक्सप्लिन विश्लेषण' पोस्ट कर सकते हैं? मैं जानना चाहता हूं कि अनुमानक क्या सोचता है। – Sean