कनेक्शन अनुकूलन

Complete

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

नोट

इस इकाई में कोड उदाहरण पायथन (साइकॉप) और .NET (Npgsql) के लिए कनेक्शन प्रबंधन पैटर्न प्रदर्शित करते हैं। इन पुस्तकालयों को बार-बार अपडेट किया जाता है। वर्तमान एपीआई विवरण के लिए साइकॉप्ग दस्तावेज़ीकरण और एनपीजीएसक्यूएल दस्तावेज़ीकरण पर जाएं।

कनेक्शन ओवरहेड

एक नया PostgreSQL कनेक्शन बनाने में कई चरण शामिल हैं, प्रत्येक विलंबता जोड़ता है:

  1. टीसीपी हैंडशेक: नेटवर्क कनेक्शन स्थापित करना (आमतौर पर 1-3 राउंड ट्रिप)
  2. टीएलएस बातचीत: कनेक्शन एन्क्रिप्ट करना (PostgreSQL के लिए Azure डेटाबेस के लिए आवश्यक)
  3. प्रमाणीकरण: क्रेडेंशियल्स की पुष्टि करना (पासवर्ड या टोकन एक्सचेंज)
  4. सर्वर प्रक्रिया आवंटन: PostgreSQL प्रत्येक कनेक्शन के लिए एक बैकएंड प्रक्रिया को जन्म देता है
  5. सत्र आरंभीकरण: सत्र पैरामीटर सेट करना और कॉन्फ़िगरेशन लोड करना

इस क्रम में नेटवर्क विलंबता और सर्वर लोड के आधार पर 50-200 मिलीसेकंड लगते हैं। प्रति सेकंड अनुरोधों के हजारों को संभालने वाले एक सिफारिश इंजन के लिए, प्रति अनुरोध नए कनेक्शन बनाने से कनेक्शन सेटअप में वास्तविक क्वेरी निष्पादन की तुलना में अधिक समय लगेगा।

PostgreSQL के लिए Azure डेटाबेस कंप्यूट टियर के आधार पर समवर्ती कनेक्शन को सीमित करता है। बर्स्टेबल B1ms 50 कनेक्शन की अनुमति देता है, सामान्य प्रयोजन 2 vCores 859 कनेक्शन की अनुमति देता है, सामान्य प्रयोजन 4 vCores 1,718 कनेक्शन की अनुमति देता है, मेमोरी ऑप्टिमाइज़्ड 4 vCores 3,437 कनेक्शन की अनुमति देता है, और मेमोरी ऑप्टिमाइज़्ड 16 vCores 5,000 कनेक्शन की अनुमति देता है। इन सीमाओं से अधिक कनेक्शन विफलताओं का कारण बनता है। प्रति अनुरोध कनेक्शन बनाने वाले एप्लिकेशन ट्रैफ़िक स्पाइक्स के दौरान इन सीमाओं को जल्दी से हिट कर सकते हैं।

PgBouncer के साथ कनेक्शन पूलिंग

PgBouncer एक हल्का कनेक्शन पूलर है जो आपके एप्लिकेशन और PostgreSQL के बीच बैठता है। यह डेटाबेस कनेक्शन का एक पूल बनाए रखता है और उनमें क्लाइंट कनेक्शन को मल्टीप्लेक्स करता है, नाटकीय रूप से आवश्यक वास्तविक डेटाबेस कनेक्शन की संख्या को कम करता है।

PostgreSQL के लिए Azure डेटाबेस में सामान्य प्रयोजन और मेमोरी ऑप्टिमाइज़्ड कंप्यूट स्तरों पर अंतर्निहित PgBouncer समर्थन शामिल है। बर्स्टेबल टियर इस सुविधा का समर्थन नहीं करता है। Azure पोर्टल या CLI के माध्यम से PgBouncer सक्षम करें। एक बार सक्षम होने पर, 6432 (सीधे PostgreSQL पोर्ट) के बजाय पोर्ट 5432 (PgBouncer पोर्ट) के माध्यम से कनेक्ट करें। PgBouncer कनेक्शन स्ट्रिंग का उपयोग करता है postgresql://user:password@myserver.postgres.database.azure.com:6432/mydb

az postgres flexible-server parameter set \
    --resource-group myResourceGroup \
    --server-name myserver \
    --name pgbouncer.enabled \
    --value true

PgBouncer तीन पूलिंग मोड का समर्थन करता है, प्रत्येक अलग-अलग ट्रेड-ऑफ के साथ। सत्र मोड का मतलब है कि क्लाइंट पूरे सत्र के लिए एक सर्वर कनेक्शन रखता है (जब तक कि डिस्कनेक्ट न हो जाए)। यह मोड सभी PostgreSQL सुविधाओं का समर्थन करता है लेकिन न्यूनतम कनेक्शन में कमी प्रदान करता है। लेन-देन मोड का अर्थ है कि एक क्लाइंट केवल लेनदेन के दौरान सर्वर कनेक्शन रखता है। लेन-देन के बीच, कनेक्शन पूल में वापस आ जाता है। यह मोड अधिकांश अनुप्रयोगों के लिए अच्छी तरह से काम करता है और कनेक्शन आवश्यकताओं को काफी कम कर देता है। स्टेटमेंट मोड का मतलब है कि क्लाइंट को केवल अलग-अलग स्टेटमेंट के लिए कनेक्शन मिलता है। यह मोड अधिकतम कनेक्शन में कमी प्रदान करता है लेकिन बहु-कथन लेनदेन का समर्थन नहीं करता है। वेक्टर खोज कार्यभार के लिए, लेनदेन मोड आमतौर पर सबसे अच्छा विकल्प होता है।

PgBouncer पूल व्यवहार, कनेक्शन सीमाएँ और टाइमआउट हैंडलिंग को नियंत्रित करने वाले कई पैरामीटर को उजागर करता है। बर्स्टी ट्रैफ़िक पैटर्न के साथ वेक्टर खोज वर्कलोड के लिए, इन मापदंडों को ट्यून करने से संसाधन खपत के खिलाफ कनेक्शन उपलब्धता को संतुलित करने में मदद मिलती है। कॉन्फ़िगर करें pgbouncer.default_pool_size (समवर्ती आवश्यकताओं pgbouncer.max_client_conn के आधार पर 20-50), (उच्च-ट्रैफ़िक अनुप्रयोगों के लिए 5000+), pgbouncer.pool_mode (लेन-देन), और pgbouncer.query_wait_timeout (30-120 सेकंड)।

हस्तांतरण मोड प्रत्येक हस्तांतरण कमिट या वापस रोल करने के बाद पूल के लिए कनेक्शन लौटाता है। यह कई PostgreSQL सुविधाओं को प्रभावित करता है। सत्र वैरिएबल लेन-देन के बीच रीसेट हो जाते हैं, इसलिए इसके साथ लागू SET की जाने वाली सेटिंग पूरे लेन-देन में बनी नहीं रहती हैं. लेन-देन के भीतर उपयोग करें SET LOCAL या डिफ़ॉल्ट सर्वर-साइड कॉन्फ़िगर करें। तैयार किए गए कथन काम नहीं कर सकते हैं क्योंकि नामित तैयार बयान कनेक्शन से बंधे होते हैं। लेन-देन मोड में, एक लेन-देन में बनाया गया एक तैयार विवरण अगले में उपलब्ध नहीं हो सकता है यदि कोई भिन्न कनेक्शन असाइन किया गया है। LISTEN/NOTIFY काम नहीं करता है क्योंकि इन सुविधाओं के लिए लगातार कनेक्शन की आवश्यकता होती है और ये लेन-देन पूलिंग के साथ असंगत होते हैं। वेक्टर खोज अनुप्रयोगों के लिए, ये सीमाएँ शायद ही कभी समस्याग्रस्त होती हैं क्योंकि क्वेरीज़ आमतौर पर सत्र-विशिष्ट स्थिति के बिना सरल चयन होती हैं।

अनुप्रयोग-स्तरीय कनेक्शन पूलिंग

PgBouncer के अलावा (या इसके बजाय), आपका एप्लिकेशन सीधे कनेक्शन पूल प्रबंधित कर सकता है। यह कनेक्शन जीवनचक्र पर बेहतर नियंत्रण प्रदान करता है और एप्लिकेशन फ्रेमवर्क के साथ एकीकृत होता है।

psycopg_pool पैकेज psycopg के लिए कनेक्शन पूलिंग प्रदान करता है। एप्लिकेशन-स्तरीय पूल आपको कनेक्शन जीवनचक्र, निष्क्रिय टाइमआउट व्यवहार और स्वास्थ्य जांच पर नियंत्रण प्रदान करते हैं। वे आपके एप्लिकेशन की त्रुटि हैंडलिंग और लॉगिंग के साथ स्वाभाविक रूप से एकीकृत होते हैं। PgBouncer के साथ संयुक्त होने पर, अनुप्रयोग पूल स्थानीय कनेक्शन प्रबंधन संभालते समय PgBouncer सर्वर-साइड मल्टीप्लेक्सिंग संभालता है। with pool.connection() संदर्भ प्रबंधक स्वचालित रूप से पूल से कनेक्शन लौटाता है जब ब्लॉक बाहर निकलता है, भले ही कोई अपवाद हो।

from psycopg_pool import ConnectionPool

# Create a connection pool
pool = ConnectionPool(
    conninfo="postgresql://user:password@myserver.postgres.database.azure.com:6432/mydb",
    min_size=5,      # Minimum connections to maintain
    max_size=20,     # Maximum connections allowed
    max_idle=300,    # Close idle connections after 5 minutes
    max_lifetime=3600  # Recycle connections after 1 hour
)

# Use connections from the pool
def search_similar_products(query_embedding, limit=10):
    with pool.connection() as conn:
        with conn.cursor() as cur:
            cur.execute("""
                SELECT id, name, embedding <=> %s AS distance
                FROM products
                ORDER BY embedding <=> %s
                LIMIT %s
            """, (query_embedding, query_embedding, limit))
            return cur.fetchall()

Npgsql में डिफ़ॉल्ट रूप से सक्षम अंतर्निहित कनेक्शन पूलिंग शामिल है, इसलिए आपको एक अलग पैकेज की आवश्यकता नहीं है। पूल स्वचालित रूप से कनेक्शन निर्माण, पुन: उपयोग और निपटान का प्रबंधन करता है जो आपके द्वारा कनेक्शन स्ट्रिंग में निर्दिष्ट मापदंडों के आधार पर होता है। प्रत्येक अद्वितीय कनेक्शन स्ट्रिंग अपने स्वयं के पूल को बनाए रखता है, इसलिए आपके एप्लिकेशन में लगातार कनेक्शन स्ट्रिंग्स कुशल पूल उपयोग सुनिश्चित करते हैं। जब आप कॉल करते conn.Close() हैं या कनेक्शन का निपटान किया जाता है, तो यह नष्ट होने के बजाय पूल में वापस आ जाता है। कनेक्शन स्ट्रिंग मापदंडों के माध्यम से पूलिंग कॉन्फ़िगर करें जैसे .Minimum Pool Size=5;Maximum Pool Size=20;Connection Idle Lifetime=300;Connection Lifetime=3600

पूल का आकार प्रदर्शन और संसाधन खपत दोनों को प्रभावित करता है। पूल को बहुत छोटा सेट करने से उपलब्ध कनेक्शन की प्रतीक्षा करने का अनुरोध होता है, जिससे विलंबता बढ़ जाती है। इसे बहुत बड़ा सेट करने से मेमोरी बर्बाद हो जाती है और डेटाबेस सर्वर पर भारी पड़ सकता है। सही आकार आपके ट्रैफ़िक पैटर्न, क्वेरी अवधि और डेटाबेस साझा करने वाले एप्लिकेशन इंस्टेंस की संख्या पर निर्भर करता है। प्रतीक्षा किए बिना आधारभूत यातायात को संभालने के लिए न्यूनतम आकार पर्याप्त बड़ा रखें। अधिकतम आकार को कैप करें जो डेटाबेस एप्लिकेशन इंस्टेंस की संख्या से विभाजित कर सकता है। यदि आपके पास 10 एप्लिकेशन इंस्टेंस हैं और आपका डेटाबेस 1,000 कनेक्शन का समर्थन करता है, तो अधिकतम 100 प्रति इंस्टेंस (हेडरूम छोड़कर) पर सेट करें। स्वास्थ्य को बनाए रखने के लिए समय-समय पर (हर 30-60 मिनट में) कनेक्शन को रीसायकल करें क्योंकि लंबे समय तक रहने वाले कनेक्शन मेमोरी लीक जमा कर सकते हैं या बासी कैश्ड योजनाओं को पकड़ सकते हैं।

एआई वर्कलोड के लिए सत्र प्रबंधन

कुछ वेक्टर क्वेरीज़ सत्र-स्तर सेटिंग्स से लाभान्वित होती हैं जो क्वेरी के लिए सर्वर-वाइड डिफ़ॉल्ट की अनुमति से अधिक संसाधन आवंटित करती हैं।

वेक्टर समानता क्वेरी जो बड़े परिणाम सेट को सॉर्ट करते हैं, वृद्धि से लाभान्वित work_memहोते हैं। इसका उपयोग करके SET LOCAL work_mem = '256MB'विशिष्ट सत्रों या लेनदेन के लिए इसे सेट करें। SET LOCAL केवल वर्तमान लेनदेन के भीतर लागू होता है। जब लेन-देन समाप्त हो जाता है, तो सेटिंग डिफ़ॉल्ट पर वापस आ जाती है, जो पूल किए गए कनेक्शन के लिए सुरक्षित है।

समायोजित करें hnsw.ef_search या विभिन्न ivfflat.probes सटीकता आवश्यकताओं के साथ प्रश्नों के लिए। उन क्वेरीज़ में उच्च रिकॉल के लिए उपयोग करें SET LOCAL hnsw.ef_search = 200 जहाँ सटीकता महत्वपूर्ण है, या तेज़ SET LOCAL hnsw.ef_search = 20 क्वेरीज़ के लिए जहाँ अनुमानित परिणाम स्वीकार्य हैं. यह पैटर्न आपको अन्य प्रश्नों को प्रभावित किए बिना विशिष्ट उपयोग के मामले के आधार पर सटीकता और गति को संतुलित करने देता है।

कुशल SDK उपयोग पैटर्न

कनेक्शन प्रबंधन से परे, आप डेटाबेस इंटरैक्शन की संरचना कैसे करते हैं, प्रदर्शन को प्रभावित करता है।

नेटवर्क राउंड ट्रिप प्रत्येक डेटाबेस ऑपरेशन में विलंबता जोड़ती हैं। जब आपको डेटा के कई टुकड़ों की आवश्यकता होती है, तो उन्हें एक ही क्वेरी में लाने से नेटवर्क ट्रांसमिशन, क्वेरी पार्सिंग और परिणाम क्रमांकन के प्रति-क्वेरी ओवरहेड को समाप्त कर दिया जाता है। एआई अनुप्रयोगों के लिए जो कई वस्तुओं के लिए एम्बेडिंग पुनर्प्राप्त करते हैं, बैचिंग कुल विलंबता को सैकड़ों मिलीसेकंड से एकल अंकों तक कम कर सकती है। अलग-अलग क्वेरी के साथ कई राउंड ट्रिप करने के बजाय, आईडी के साथ एक WHERE id = ANY(%s) ही क्वेरी का उपयोग करें और पास करें।

बड़ी संख्या में वैक्टर लोड करने के लिए, PostgreSQL COPY कमांड अलग-अलग INSERT बयानों की तुलना में नाटकीय रूप से तेज़ है। COPY डेटा को सीधे बाइनरी या टेक्स्ट प्रारूप में तालिका में स्ट्रीम करता है, अलग-अलग SQL कथनों को पार्स करने के ओवरहेड को दरकिनार करता है। बैच प्रोसेसिंग पाइपलाइनों या प्रारंभिक डेटा माइग्रेशन से एम्बेड डेटा लोड करते समय, COPY लोड समय को घंटों से मिनटों तक कम कर सकता है। COPY प्रति सेकंड सैकड़ों हजारों पंक्तियों को लोड कर सकते हैं, जबकि व्यक्तिगत आवेषण प्रति सेकंड हजारों तक सीमित हैं।

जब आपका अनुप्रयोग काम को parallelize कर सकते हैं, तो async डेटाबेस कार्रवाई थ्रेड्स को अवरुद्ध किए बिना एक साथ कई क्वेरीज़ निष्पादित करके थ्रूपुट में सुधार करते हैं। यह पैटर्न एआई वर्कलोड के लिए मूल्यवान है जिसे एक साथ कई वेक्टर संग्रहों को खोजने या वेक्टर खोज को अन्य डेटा पुनर्प्राप्ति के साथ संयोजित करने की आवश्यकता होती है। Async पूल पूल आकार सीमाओं का सम्मान करते हुए समवर्ती संचालन में कनेक्शन को कुशलतापूर्वक प्रबंधित करते हैं। psycopg_pool से उपयोग करें AsyncConnectionPool और asyncio.gather एक साथ कई खोजों को निष्पादित करें।

कनेक्शन लचीलापन

नेटवर्क समस्याएँ, सर्वर पुनरारंभ हो जाता है, और विफलताएँ डेटाबेस कनेक्शन को बाधित कर सकती हैं। मजबूत एप्लिकेशन इन्हें इनायत से संभालते हैं।

रखरखाव के दौरान नेटवर्क ब्लिप्स, कनेक्शन रीसेट और संक्षिप्त सर्वर अनुपलब्धता जैसी क्षणिक विफलताएं क्लाउड वातावरण में अपरिहार्य हैं। घातीय बैकऑफ़ के साथ पुन: प्रयास तर्क को लागू करने से आपके एप्लिकेशन को तत्काल पुन: प्रयास प्रयासों के साथ सर्वर को अभिभूत किए बिना इन अस्थायी समस्याओं से इनायत से पुनर्प्राप्त करने में मदद मिलती है। एक साथ पुन: प्रयास करने से कई अनुप्रयोग आवृत्तियों को रोकने के लिए यादृच्छिक घबराहट जोड़ें। अपवादों को पकड़ें OperationalError , प्रतीक्षा समय की गणना करें (2 ** attempt) + random.uniform(0, 1), और अधिकतम संख्या में प्रयासों तक पुनः प्रयास करें।

टाइमआउट आपके एप्लिकेशन को अनिश्चित काल तक प्रतीक्षा करने से रोकता है जब डेटाबेस धीमा या पहुंच योग्य नहीं है। कनेक्शन टाइमआउट सीमित है कि नए कनेक्शन स्थापित करते समय कितनी देर तक प्रतीक्षा करें, जबकि कथन टाइमआउट क्वेरी निष्पादन समय को सीमित करते हैं। वेक्टर खोज अनुप्रयोगों के लिए, ऐसे टाइमआउट चुनें जो आपके सबसे धीमे वैध प्रश्नों को समायोजित करते हैं, जबकि स्वीकार्य विलंबता से अधिक प्रश्नों पर तेजी से विफल होते हैं। और जैसे options=-c statement_timeout=30000पैरामीटर connect_timeout=10 का उपयोग करके अपने कनेक्शन स्ट्रिंग में टाइमआउट कॉन्फ़िगर करें। वेक्टर क्वेरीज़ के लिए, स्टेटमेंट टाइमआउट सेट करें जो आपके सबसे धीमे स्वीकार्य क्वेरीज़ को समायोजित करते हैं. जटिल वेक्टर खोजों के लिए 30 सेकंड का टाइमआउट उचित है; इंटरएक्टिव एप्लिकेशन कम मानों का उपयोग कर सकते हैं।

जब सभी पूल कनेक्शन उपयोग में हैं और नए अनुरोध आते हैं, तो पूल को या तो अनुरोधों को पंक्तिबद्ध करना होगा (विलंबता जोड़ना) या उन्हें तुरंत अस्वीकार करना होगा। कोई भी विकल्प आदर्श नहीं है, इसलिए पूल उपयोग की निगरानी करने से आपको थकावट बार-बार होने से पहले स्केल करने में मदद मिलती है। जब थकावट होती है, तो एक स्पष्ट त्रुटि संदेश लौटाने में क्लाइंट को अप्रत्याशित रूप से समय देने के बजाय अपने स्वयं के पुन: प्रयास तर्क को कार्यान्वित करने में मदद करता है। एक सुंदर त्रुटि {"error": "Service temporarily busy, please retry"}लौटाकर अपवादों को संभालें PoolTimeout जैसे . पूल के उपयोग और पैमाने की निगरानी करें यदि थकावट अक्सर होती है।

अतिरिक्त संसाधन