2010-12-03 16 views
6

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

शायद मैं सभी लॉकिंग, सुरक्षा जांच, ट्रिगर्स इत्यादि बंद कर सकता हूं? बस एक त्वरित और गंदे समाधान की तलाश है जो इस प्रक्रिया को बहुत तेज कर देगा।

धन्यवाद।

उत्तर

8

यदि आपको उत्पादन वातावरण में उस तरह की कार्यक्षमता की आवश्यकता नहीं है, तो मैं सुझाव दूंगा कि आप अपने PostgreSQL कॉन्फ़िगरेशन से fsync को बंद कर दें। इससे नाटकीय रूप से आवेषण तेज हो जाएंगे।

कभी भी उत्पादन डेटाबेस पर fsync को बंद न करें।

+1

stdin से इनपुट लेता है मैं मानता हूँ: fsync कभी नहीं उत्पादन में बंद कर दिया जाना चाहिए (जब तक आप है एक बहुत ही विश्वसनीय बैटरी समर्थित नियंत्रक)। लेकिन synchronous_commit = झूठी वास्तव में चीजों में सुधार कर सकती है और एक बड़ा जोखिम नहीं लगाती –

+0

मेरे परीक्षण वातावरण में 'synchronous_commit' ने अंतर होने के लिए पर्याप्त गति में सुधार नहीं किया है। आईआईआरसी ने इसे 2 मिनट डीबी निर्माण और आबादी की प्रक्रिया में आधा कर दिया, लेकिन fsync को बंद करने से इसे 10 सेकंड में चलाया गया। मेरे पास हजारों रिकॉर्ड नहीं हैं इसलिए मेरा टेस्ट डेटाबेस कभी भी fsync = off' के साथ डिस्क को हिट नहीं करता है। – jmz

+3

एक बैटरी समर्थित कैश आपको fsync बंद होने से बचा नहीं सकता है! यदि डिस्क पर डेटा लिखा जाने से पहले, आपका ओएस क्रैश हो जाता है या नकली fsync होने के बाद बिजली खो देता है, तो आप डेटा खो देंगे। पूर्ण पृष्ठ के बारे में भी प्रश्न हैं जो अभी भी बीबीयू कैशिंग RAID नियंत्रकों पर 100% सुरक्षित हैं। –

3

एक चीज जो आप कर सकते हैं वह सभी इंडेक्स को हटा दें, अपने आवेषण करें, और फिर इंडेक्स को फिर से बनाएं।

2

क्या आप हजारों INSERTs या के बैच भेज रहे हैं क्या आप हजारों INSERT भेज रहे हैं?

मुझे हाइबरनेट के साथ पता है कि आप अपने सभी एसक्यूएल स्टेटमेंट्स को बैच कर सकते हैं और उन्हें हजारों एसक्यूएल कथन व्यक्तिगत रूप से बनाने के नेटवर्क और डेटाबेस ओवरहेड के कर लेने के बजाय एक बड़े हिस्से में अंत में भेज सकते हैं।

8

सबसे तेज़ तरीका सम्मिलित करने के लिए डेटा COPY आदेश होगा। लेकिन इसके इनपुट के रूप में एक फ्लैट फ़ाइल की आवश्यकता है। मुझे लगता है कि एक फ्लैट फ़ाइल उत्पन्न करना एक विकल्प नहीं है।

अक्सर मत करो, विशेष रूप से ऑटोकॉमिट सक्षम के साथ इसे चलाएं। "हजारों लोगों" अंत में एक ही प्रतिबद्धता की तरह लगता है बस सही होगा।

आपको लगता है कि चीजों के साथ-साथ

में तेजी लाने के हैं यह एक बहु-पंक्ति सम्मिलित करने का एक उदाहरण है Postgres 'बहु-पंक्ति सम्मिलित करने का उपयोग करने के अपने ORM convice कर सकते हैं:

 
insert into my_table (col1, col2) 
values 
(row_1_col_value1, row_1_col_value_2), 
(row_2_col_value1, row_2_col_value_2), 
(row_3_col_value1, row_3_col_value_2) 

हैं आप ऊपर वाक्य रचना उत्पन्न नहीं कर सकते और आप जावा सुनिश्चित करें कि आप एक बयान आवेषण के बजाय बैच बयान उपयोग कर रहे हैं का उपयोग कर रहे (शायद अन्य डीबी परतों कुछ इसी तरह की अनुमति देने के)

संपादित करें:

jmz 'पोस्ट मुझे कुछ जोड़ने के लिए प्रेरित:

तुम भी एक सुधार जब आप कुछ बड़ा मूल्य को wal_buffers वृद्धि देख सकते हैं (उदाहरण के लिए 8 एमबी) और checkpoint_segments (उदाहरण के लिए 16)

+0

सीओपीवाई के लिए +1। गति के लिए सबसे अच्छा तरीका। – karlgrz

+1

प्रतिलिपि आदेश एक फ्लैट फ़ाइल की आवश्यकता नहीं है, के रूप में यह में मानक से इनपुट ले सकते हैं। अपने डाटाबेस के एक प्लेन टेक्स्ट बैकअप बनाने और आप इसे stdin शामिल प्रतिलिपि आदेशों का पूरा देखेंगे। –

+2

@ स्कॉट: आप सही हैं। लेकिन प्रारूप अभी भी एक "सादा पाठ" प्रारूप है। तो क्रम में तेजी से कॉपी तंत्र का लाभ लेने के लिए, मौजूदा कार्यक्रम के पुनर्लेखन के लिए प्रयास मूलतः एक ही है कि क्या कॉपी यह एक फ़ाइल से या –

6

आवेषण के लिए हजारों सैकड़ों में है कि संख्या, उन्हें बैच:

COPY test (ts) FROM stdin; 
2010-11-29 22:32:01.383741-07 
2010-11-29 22:32:01.737722-07 
... 1Million rows 
\. 

यकीन है कि किसी भी एक और तालिका में एक FK रूप में इस्तेमाल किया col करें:

begin; 
insert1 ... 
insert2 ... 
... 
insert10k ... 
commit; 

लाखों में आवेषण के लिए प्रति का उपयोग अगर यह अन्य तालिका में आकार में तुच्छ से अधिक है तो अनुक्रमित किया गया है।

2

तुम सिर्फ लगातार परीक्षण डाटा आरंभ कर रहे हैं, तो आप भी परीक्षण डाटा एक मचान तालिका (रों) में जितनी जल्दी डाल सकता है, तो बस तालिका सामग्री की प्रतिलिपि,

INSERT INTO... SELECT... 

का उपयोग कर के बारे में होना चाहिए COPY का उपयोग करके (हालांकि मैंने इसे बेंचमार्क नहीं किया है), लाभ के साथ आप केवल SQL आदेशों का उपयोग करके प्रतिलिपि बना सकते हैं, बिना बाहरी फ़ाइल को स्थापित करने की परेशानी के बिना।

2

कोशिश एक अनुरोध में जितना संभव हो उतना करने के लिए!

insert into my_table (col1, col2) 
values (
    unnest(array[row_1_col_value_1, row_2_col_value_1, row3_col_value_1]), 
    unnest(array[row_1_col_value_2, row_2_col_value_2, row_3_col_value_2)); 

यह @a_horse_with_no_name के सुझाव जैसा दिखता है। unnest का उपयोग करने का लाभ यह है: आप उन क्वेरी पैरामीटर का उपयोग कर सकते हैं जिनमें सरणी हैं!

insert into my_table (col1, col2) 
values (unnest(:col_values_1), unnest(:col_values_2)); 

एक में तीन insert बयान गिर रखकर आप निष्पादन समय के 50% से अधिक को बचाने के। और एक एकल Insert में 2000 मूल्यों के साथ क्वेरी पैरामीटर का उपयोग करके, मैं 150 की रफ्तार कारक अपने आवेदन में मिलता है।