मैं अपना खुद का जवाब जोड़ रहा हूं क्योंकि मैं वर्तमान में स्वीकार किए गए एक से असहमत हूं। यह कहता है कि ऑपरेशन थ्रेड-सुरक्षित नहीं है, लेकिन यह सादा गलत है - SQLite uses file locking यह सुनिश्चित करने के लिए कि वर्तमान में ACID का पालन करें, वर्तमान प्लेटफ़ॉर्म के लिए उपयुक्त है।
यूनिक्स सिस्टम पर यह fcntl()
या flock()
लॉकिंग होगा, जो प्रति-फ़ाइल हैंडल लॉक है। नतीजतन, कोड पोस्ट किया गया है जो हर बार एक नया कनेक्शन बनाता है हमेशा एक नया फाइलहेडल आवंटित करेगा और इसलिए SQLite का अपना लॉकिंग डेटाबेस भ्रष्टाचार को रोक देगा। इसका एक परिणाम यह है कि एनएफएस शेयर या इसी तरह SQLite का उपयोग करना आम तौर पर एक बुरा विचार है, क्योंकि अक्सर यह विशेष रूप से विश्वसनीय लॉकिंग प्रदान नहीं करता है (हालांकि यह आपके एनएफएस कार्यान्वयन पर निर्भर करता है)।
जैसा कि @बर्नर्ट ने पहले ही टिप्पणियों में SQLite has had issues with threads में बताया है, लेकिन यह धागे के बीच एक कनेक्शन साझा करने से संबंधित था। जैसा कि वह भी उल्लेख करता है, इसका मतलब है कि यदि आप एक एप्लिकेशन-व्यापी पूल का उपयोग करते हैं तो आपको रनटाइम त्रुटियां मिलेंगी यदि दूसरा थ्रेड पूल से रीसाइक्लिंग कनेक्शन खींचता है। ये भी परेशान करने वाली बग्स की तरह हैं जिन्हें आप परीक्षण में नहीं देख सकते हैं (हल्का भार, शायद उपयोग में केवल एक धागा), लेकिन जो आसानी से बाद में सिरदर्द का कारण बन सकता है। मार्टिजन पीटर्स के बाद में थ्रेड-स्थानीय पूल के सुझाव को ठीक काम करना चाहिए।
संस्करण के रूप में SQLite FAQ में दिखाया गया है 3.3.1 यह रूप में लंबे समय धागे के बीच कनेक्शन पारित करने के लिए वास्तव में सुरक्षित है क्योंकि वे किसी भी ताले पकड़ नहीं है - यह एक रियायत है कि SQLite के लेखक के महत्वपूर्ण होने के बावजूद जोड़ा था सामान्य रूप से धागे का उपयोग।कोई समझदार कनेक्शन पूलिंग कार्यान्वयन हमेशा यह सुनिश्चित करेगा कि पूल में कनेक्शन को बदलने से पहले सब कुछ या तो किया गया है या फिर लुढ़का गया है, इसलिए वास्तव में एक एप्लिकेशन-ग्लोबल पूल संभवतः सुरक्षित होगा अगर यह साझा करने के खिलाफ पायथन चेक के लिए नहीं था , जो मुझे लगता है कि SQLite का एक नवीनतम संस्करण उपयोग किया जाता है, भले ही मेरा मानना है। निश्चित रूप से मेरे पायथन 2.7.3 सिस्टम में sqlite3
मॉड्यूल sqlite_version_info
रिपोर्टिंग 3.7.9 है, फिर भी यह RuntimeError
फेंकता है यदि आप इसे एकाधिक थ्रेड से एक्सेस करते हैं।
किसी भी मामले में, चेक मौजूद होने पर कनेक्शन को प्रभावी रूप से साझा नहीं किया जा सकता है भले ही अंतर्निहित SQLite लाइब्रेरी इसका समर्थन करे।
आपके मूल प्रश्न के रूप में, निश्चित रूप से कनेक्शन के पूल को रखने से हर बार एक नया कनेक्शन बनाना कम कुशल होता है, लेकिन पहले ही उल्लेख किया जा चुका है कि इसे थ्रेड-स्थानीय पूल होना आवश्यक है, जो लागू करने के लिए थोड़ा सा दर्द है । डेटाबेस में नया कनेक्शन बनाने का ओवरहेड अनिवार्य रूप से फ़ाइल खोल रहा है और यह सुनिश्चित करने के लिए हेडर पढ़ रहा है कि यह वैध SQLite फ़ाइल है। वास्तव में एक कथन निष्पादित करने का ओवरहेड अधिक होता है क्योंकि इसे देखने के लिए और फ़ाइल I/O का प्रदर्शन करने की आवश्यकता होती है, इसलिए काम का बड़ा हिस्सा वास्तव में कथन निष्पादन और/या प्रतिबद्ध होने तक स्थगित कर दिया जाता है।
दिलचस्प बात यह है कि, कम से कम लिनक्स सिस्टम पर मैंने कथन निष्पादित करने के लिए कोड को फ़ाइल हेडर पढ़ने के चरणों को दोहराया है - नतीजतन, एक नया कनेक्शन खोलना इतना बुरा नहीं होगा चूंकि कनेक्शन खोलते समय प्रारंभिक पढ़ने से हेडर को सिस्टम के फाइल सिस्टम कैश में खींच लिया जाएगा। तो यह एक एकल फ़ाइल खोलने के ऊपरी हिस्से में उबाल जाता है।
मुझे यह भी जोड़ना चाहिए कि यदि आप अपने कोड को उच्च समेकन तक स्केल करने की उम्मीद कर रहे हैं तो SQLite खराब विकल्प हो सकता है। their own website points out के रूप में यह उच्च समेकन के लिए वास्तव में उपयुक्त नहीं है क्योंकि एक वैश्विक लॉक के माध्यम से सभी पहुंच को निचोड़ने के प्रदर्शन हिट को समेकित धागे की संख्या बढ़ने लगती है। यह ठीक है अगर आप सुविधा के लिए धागे का उपयोग कर रहे हैं, लेकिन यदि आप वास्तव में उच्च स्तर की समेकन की उम्मीद कर रहे हैं तो मैं SQLite से बचूंगा।
संक्षेप में, मुझे नहीं लगता कि हर बार खोलने का आपका दृष्टिकोण वास्तव में इतना बुरा है। क्या थ्रेड-स्थानीय पूल प्रदर्शन में सुधार कर सकता है? शायद हाँ। क्या यह प्रदर्शन लाभ ध्यान देने योग्य होगा? मेरी राय में, जब तक कि आप बहुत अधिक कनेक्शन दरों को नहीं देख रहे हैं, और उस समय आपके पास बहुत सारे धागे होंगे ताकि आप शायद SQLite से दूर जाना चाहें क्योंकि यह समेकन को अच्छी तरह से संभाल नहीं लेता है। यदि आप एक का उपयोग करने का निर्णय लेते हैं, तो सुनिश्चित करें कि यह पूल पर लौटने से पहले कनेक्शन को साफ़ कर देता है - SQLAlchemy में कुछ connection pooling कार्यक्षमता है जो आपको उपयोगी मिल सकती है भले ही आप सभी ओआरएम परतों को शीर्ष पर नहीं चाहते हैं।
संपादित
के रूप में काफी हद बताया मैं वास्तविक समय देते हैं चाहिए। ये काफी कम संचालित वीपीएस से हैं:
>>> timeit.timeit("cur = conn.cursor(); cur.execute('UPDATE foo SET name=\"x\"
WHERE id=3'); conn.commit()", setup="import sqlite3;
conn = sqlite3.connect('./testdb')", number=100000)
5.733098030090332
>>> timeit.timeit("conn = sqlite3.connect('./testdb'); cur = conn.cursor();
cur.execute('UPDATE foo SET name=\"x\" WHERE id=3'); conn.commit()",
setup="import sqlite3", number=100000)
16.518677949905396
आप लगभग 3x अंतर का एक कारक देख सकते हैं, जो महत्वहीन नहीं है। हालांकि, पूर्ण समय अभी भी उप-मिलीसेकंड है, इसलिए जब तक आप प्रति अनुरोध के बहुत से प्रश्न नहीं करते हैं, तो शायद पहले अनुकूलित करने के लिए अन्य स्थान हैं। यदि आप बहुत सारे प्रश्न पूछते हैं, तो एक उचित समझौता प्रति अनुरोध एक नया कनेक्शन हो सकता है (लेकिन पूल की जटिलता के बिना, बस हर बार फिर से कनेक्ट करें)।
पढ़ने के लिए (यानी चयन करें) तो प्रत्येक बार कनेक्ट करने के सापेक्ष ओवरहेड अधिक होंगे, लेकिन दीवार घड़ी के समय में पूर्ण ओवरहेड सुसंगत होना चाहिए।
जैसा कि इस प्रश्न पर कहीं और चर्चा की जा चुकी है, आपको वास्तविक प्रश्नों के साथ परीक्षण करना चाहिए, मैं बस दस्तावेज बनाना चाहता था जो मैंने अपने निष्कर्षों पर करने के लिए किया था।
कृपया 'ओपन' और 'findall' के बजाय 'कनेक्ट' और' fetchall' जैसे सही कार्यों के साथ वास्तविक कोड पोस्ट करें। – abarnert
आपके पास "कोड के विभिन्न बिट्स के साथ समस्याएं" क्या हैं? यदि आप एकाधिक समवर्ती लिखने की कोशिश कर रहे हैं, तो असली आरडीबीएमएस का उपयोग करें http://www.sqlite.org/faq.html#q5 – msw