यहां कई कारक काम कर रहे हैं:
- नेटवर्क विलंबता और राउंड-ट्रिप विलंब
- PostgreSQL में प्रति-स्टेटमेंट ओवरहेड्स
- संदर्भ स्विच और शेड्यूलर विलंब
COMMIT
लागत, यदि प्रति इंसर्ट एक कमिट करने वाले लोगों के लिए (आप नहीं हैं)COPY
-बल्क लोडिंग के लिए विशिष्ट अनुकूलन
नेटवर्क प्रतीक्षा अवधि
यदि सर्वर दूरस्थ है, तो आप प्रति-कथन निश्चित समय "कीमत" का "भुगतान" कर सकते हैं, कहते हैं, 50ms (एक सेकंड का 1/20 वां)। या कुछ क्लाउड होस्टेड डीबी के लिए और भी बहुत कुछ। चूंकि अगला इंसर्ट तब तक शुरू नहीं हो सकता जब तक कि आखिरी इंसर्ट सफलतापूर्वक पूरा न हो जाए, इसका मतलब है कि आपका अधिकतम इंसर्ट की दर 1000/राउंड-ट्रिप-लेटेंसी-इन-एमएस पंक्तियाँ प्रति सेकंड है। 50ms ("पिंग टाइम") की विलंबता पर, वह 20 पंक्तियाँ/सेकंड है। स्थानीय सर्वर पर भी, यह विलंब शून्य नहीं है। जबकि COPY
बस टीसीपी भरता है और विंडोज़ प्राप्त करता है, और पंक्तियों को उतनी ही तेजी से स्ट्रीम करता है जितना डीबी उन्हें लिख सकता है और नेटवर्क उन्हें स्थानांतरित कर सकता है। यह विलंबता से अधिक प्रभावित नहीं होता है, और हो सकता है कि एक ही नेटवर्क लिंक पर प्रति सेकंड हज़ारों पंक्तियाँ सम्मिलित कर रहा हो।
PostgreSQL में प्रति-कथन लागत
PostgreSQL में एक बयान को पार्स करने, योजना बनाने और निष्पादित करने की लागत भी है। इसमें लॉक, ओपन रिलेशन फाइल्स, लुक अप इंडेक्स आदि होने चाहिए। COPY
शुरुआत में यह सब एक बार करने की कोशिश करता है, फिर जितनी जल्दी हो सके पंक्तियों को लोड करने पर ध्यान केंद्रित करें।
कार्य/संदर्भ स्विचिंग लागत
आपके ऐप को तैयार करने और भेजने के दौरान ऑपरेटिंग सिस्टम को एक पंक्ति के लिए प्रतीक्षा कर रहे पोस्टग्रेज़ के बीच स्विच करने के कारण और समय की लागत का भुगतान किया जाता है, और फिर आपका ऐप पोस्टग्रेज़ की प्रतिक्रिया की प्रतीक्षा करता है जबकि पोस्टग्रेज़ पंक्ति को संसाधित करता है। हर बार जब आप एक से दूसरे में स्विच करते हैं, तो आप थोड़ा समय बर्बाद करते हैं। प्रक्रियाओं में प्रवेश करने और प्रतीक्षा अवस्था छोड़ने पर विभिन्न निम्न स्तर की कर्नेल अवस्था को निलंबित करने और फिर से शुरू करने में अधिक समय संभावित रूप से बर्बाद होता है।
कॉपी ऑप्टिमाइज़ेशन से वंचित
इन सबसे ऊपर, COPY
इसमें कुछ अनुकूलन हैं जिनका उपयोग यह कुछ प्रकार के भारों के लिए कर सकता है। यदि कोई जेनरेट की गई कुंजी नहीं है और उदाहरण के लिए कोई भी डिफ़ॉल्ट मान स्थिरांक हैं, तो यह उन्हें पूर्व-गणना कर सकता है और निष्पादक को पूरी तरह से बायपास कर सकता है, निचले स्तर पर तालिका में तेजी से लोड हो रहा डेटा जो पोस्टग्रेएसक्यूएल के सामान्य काम के हिस्से को पूरी तरह से छोड़ देता है। अगर आप CREATE TABLE
या TRUNCATE
उसी लेन-देन में आप COPY
, यह एक बहु-क्लाइंट डेटाबेस में आवश्यक सामान्य लेन-देन बहीखाता पद्धति को दरकिनार करके लोड को तेज़ करने के लिए और भी अधिक तरकीबें कर सकता है।
इसके बावजूद, PostgreSQL की COPY
चीजों को गति देने के लिए अभी भी बहुत कुछ कर सकता है, ऐसी चीजें जिन्हें वह अभी तक नहीं जानता कि कैसे करना है। यदि आप तालिका के एक निश्चित अनुपात से अधिक बदल रहे हैं तो यह स्वचालित रूप से इंडेक्स अपडेट को छोड़ सकता है और इंडेक्स को फिर से बना सकता है। यह बैचों में इंडेक्स अपडेट कर सकता है। और भी बहुत कुछ।
लागत कम करें
विचार करने के लिए एक अंतिम बात प्रतिबद्ध लागत है। यह शायद आपके लिए कोई समस्या नहीं है क्योंकि psycopg2
लेन-देन खोलने में चूक करता है और तब तक प्रतिबद्ध नहीं होता जब तक आप इसे नहीं बताते। जब तक आपने इसे ऑटोोकॉमिट का उपयोग करने के लिए नहीं कहा। लेकिन कई डीबी ड्राइवरों के लिए ऑटोोकॉमिट डिफ़ॉल्ट है। ऐसे मामलों में आप प्रत्येक INSERT
. के लिए एक कमिटमेंट कर रहे होंगे . इसका मतलब है कि एक डिस्क फ्लश, जहां सर्वर यह सुनिश्चित करता है कि वह डिस्क पर मेमोरी में सभी डेटा लिखता है और डिस्क को अपने कैश को लगातार स्टोरेज में लिखने के लिए कहता है। इसमें लंबा लग सकता है समय, और हार्डवेयर के आधार पर बहुत कुछ बदलता है। मेरा SSD-आधारित NVMe BTRFS लैपटॉप केवल 200 fsyncs/सेकंड, बनाम 300,000 नॉन-सिंक राइट/सेकंड कर सकता है। तो यह केवल 200 पंक्तियों/सेकंड लोड करेगा! कुछ सर्वर केवल 50 fsyncs/सेकंड ही कर सकते हैं। कुछ 20,000 कर सकते हैं। इसलिए यदि आपको नियमित रूप से कमिटमेंट करना है, तो बैचों में लोड और कमिट करने का प्रयास करें, मल्टी-रो इंसर्ट आदि करें। क्योंकि COPY
अंत में केवल एक ही प्रतिबद्ध होता है, प्रतिबद्ध लागत नगण्य होती है। लेकिन इसका मतलब यह भी है COPY
डेटा के माध्यम से त्रुटियों से आंशिक रूप से पुनर्प्राप्त नहीं हो सकता; यह संपूर्ण बल्क लोड को पूर्ववत कर देता है।