डेटाबेस प्रबंधन बैकएंड विकास के सबसे महत्वपूर्ण पहलुओं में से एक है। एक उचित रूप से अनुकूलित डेटाबेस प्रतिक्रिया समय को कम करने में मदद कर सकता है और इसलिए बेहतर उपयोगकर्ता अनुभव प्रदान करता है।
इस लेख में, हम Django अनुप्रयोगों में गति के लिए डेटाबेस को अनुकूलित करने के तरीकों पर चर्चा करेंगे। हालांकि, हम व्यक्तिगत रूप से प्रत्येक अवधारणा में गहराई से गोता नहीं लगाएंगे, इसलिए, कृपया पूर्ण विवरण के लिए देखें।
Django में क्वेरीसेट को समझना अनुकूलन की कुंजी है, इसलिए, कृपया निम्नलिखित को याद रखें:
len()
, count()
आदि द्वारा किया जा सकता है। सुनिश्चित करें कि आप उनका सबसे अच्छा उपयोग करते हैं।
डेटाबेस इंडेक्सिंग डेटाबेस से रिकॉर्ड प्राप्त करते समय प्रश्नों को तेज करने की एक तकनीक है। जैसे-जैसे एप्लिकेशन आकार में बढ़ता है, यह धीमा हो सकता है, और उपयोगकर्ता नोटिस करेंगे क्योंकि आवश्यक डेटा प्राप्त करने में काफी अधिक समय लगेगा। इस प्रकार, बड़े डेटाबेस के साथ काम करते समय अनुक्रमण एक गैर-परक्राम्य ऑपरेशन है जो बड़ी मात्रा में डेटा उत्पन्न करता है।
अनुक्रमण विभिन्न क्षेत्रों के आधार पर बड़ी संख्या में डेटा को छाँटने की एक विधि है। जब आप किसी डेटाबेस में किसी फ़ील्ड पर एक अनुक्रमणिका बनाते हैं, तो आप एक अन्य डेटा संरचना बनाते हैं जिसमें फ़ील्ड मान के साथ-साथ उस रिकॉर्ड का सूचक भी होता है जिससे वह संबंधित होता है। इस अनुक्रमणिका संरचना को तब क्रमबद्ध किया जाता है, जिससे बाइनरी खोज संभव हो जाती है।
उदाहरण के लिए, यहां सेल नाम का एक Django मॉडल है:
# models.py from django.db import models class Sale(models.Model): sold_at = models.DateTimeField( auto_now_add=True, ) charged_amount = models.PositiveIntegerField()
एक Django मॉडल को परिभाषित करते हुए डेटाबेस इंडेक्सिंग को एक विशेष क्षेत्र में जोड़ा जा सकता है:
# models.py from django.db import models class Sale(models.Model): sold_at = models.DateTimeField( auto_now_add=True, db_index=True, #DB Indexing ) charged_amount = models.PositiveIntegerField()
यदि आप इस मॉडल के लिए माइग्रेशन चलाते हैं, तो Django टेबल सेल्स पर एक डेटाबेस इंडेक्स बनाएगा, और यह इंडेक्स पूरा होने तक लॉक रहेगा। स्थानीय विकास सेटअप पर, डेटा की एक छोटी मात्रा और बहुत कम कनेक्शन के साथ, यह माइग्रेशन तात्कालिक लग सकता है, लेकिन जब हम उत्पादन वातावरण के बारे में बात करते हैं, तो कई समवर्ती कनेक्शन वाले बड़े डेटासेट होते हैं जो लॉक प्राप्त करने और बनाने के रूप में डाउनटाइम का कारण बन सकते हैं। एक डेटाबेस इंडेक्स में बहुत समय लग सकता है।
आप नीचे दिखाए गए अनुसार दो क्षेत्रों के लिए एक एकल अनुक्रमणिका भी बना सकते हैं:
# models.py from django.db import models class Sale(models.Model): sold_at = models.DateTimeField( auto_now_add=True, db_index=True, #DB Indexing ) charged_amount = models.PositiveIntegerField() class Meta: indexes = [ ["sold_at", "charged_amount"]]
डेटाबेस कैशिंग डेटाबेस से तेज़ प्रतिक्रिया प्राप्त करने के सर्वोत्तम तरीकों में से एक है। यह सुनिश्चित करता है कि ओवरलोड को रोकने के लिए डेटाबेस में कम कॉल की जाती है। एक मानक कैशिंग ऑपरेशन निम्न संरचना का अनुसरण करता है:
Django एक कैशिंग तंत्र प्रदान करता है जो मेमकैच्ड और रेडिस जैसे विभिन्न कैशिंग बैकएंड का उपयोग कर सकता है जो आपको एक ही क्वेरी को कई बार चलाने से बचने देता है।
Memcached एक ओपन-सोर्स इन-मेमोरी सिस्टम है जो एक मिलीसेकंड से भी कम समय में कैश्ड परिणाम प्रदान करने की गारंटी देता है। इसे स्थापित करना और स्केल करना आसान है। दूसरी ओर, Redis, Memcached के समान विशेषताओं वाला एक ओपन-सोर्स कैशिंग समाधान है। अधिकांश ऑफ़लाइन ऐप्स पहले से संचित डेटा का उपयोग करते हैं, जिसका अर्थ है कि अधिकांश क्वेरीज़ कभी भी डेटाबेस तक नहीं पहुँचती हैं।
उपयोगकर्ता सत्र आपके Django एप्लिकेशन में कैश में सहेजे जाने चाहिए, और क्योंकि Redis डिस्क पर डेटा बनाए रखता है, लॉग-इन उपयोगकर्ताओं के लिए सभी सत्र डेटाबेस के बजाय कैश से उत्पन्न होते हैं।
Django के साथ Memcache का उपयोग करने के लिए, हमें निम्नलिखित को परिभाषित करने की आवश्यकता है:
ip:port
मान जहां ip
मेमकैच्ड डेमॉन का आईपी पता है और port
वह पोर्ट है जिस पर मेम्केड चल रहा है, या URL आपके रेडिस इंस्टेंस की ओर इशारा करते हुए, उपयुक्त योजना का उपयोग कर रहा है।
Memcached के साथ डेटाबेस कैशिंग को सक्षम करने के लिए, निम्न आदेश का उपयोग करके पाइप का उपयोग करके pymemcache
स्थापित करें:
pip install pymemcache
फिर, आप अपनी settings.py
में कैशे सेटिंग्स को निम्नानुसार कॉन्फ़िगर कर सकते हैं:
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache', 'LOCATION': '127.0.0.1:11211', } }
उपरोक्त उदाहरण में, Memcached pymemcache
बाइंडिंग का उपयोग करके लोकलहोस्ट (127.0.0.1) पोर्ट 11211 पर चल रहा है:
इसी तरह, रेडिस का उपयोग करके डेटाबेस कैशिंग को सक्षम करने के लिए, नीचे दिए गए कमांड का उपयोग करके पाइप का उपयोग करके रेडिस स्थापित करें:
pip install redis
फिर निम्न कोड जोड़कर अपनी settings.py
में कैशे सेटिंग्स को कॉन्फ़िगर करें:
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379', } }
Memcached और Redis का उपयोग उपयोगकर्ता प्रमाणीकरण टोकन को संग्रहीत करने के लिए भी किया जा सकता है। क्योंकि लॉग इन करने वाले प्रत्येक व्यक्ति को टोकन की आपूर्ति करनी होगी, इन सभी प्रक्रियाओं के परिणामस्वरूप महत्वपूर्ण डेटाबेस ओवरहेड हो सकता है। कैश्ड टोकन का उपयोग करने से डेटाबेस तक काफी तेजी से पहुंच होगी।
Django में एक क्वेरीसेट, आमतौर पर, मूल्यांकन होने पर इसके परिणाम को कैश करता है और उस क्वेरीसेट के साथ किसी भी आगे के संचालन के लिए, यह पहले जांचता है कि कैश किए गए परिणाम हैं या नहीं। हालांकि, जब आप iterator()
का उपयोग करते हैं, तो यह कैश की जांच नहीं करता है और सीधे डेटाबेस से परिणाम पढ़ता है, न ही परिणामों को क्वेरीसेट में सहेजता है।
अब, आप सोच रहे होंगे कि यह कैसे मददगार है। एक क्वेरीसेट पर विचार करें जो बड़ी संख्या में ऑब्जेक्ट्स को कैश करने के लिए बहुत सारी मेमोरी देता है लेकिन केवल एक बार उपयोग किया जाना है, ऐसे मामले में, आपको iterator()
का उपयोग करना चाहिए।
उदाहरण के लिए, निम्नलिखित कोड में, सभी रिकॉर्ड डेटाबेस से प्राप्त किए जाएंगे और फिर मेमोरी में लोड किए जाएंगे और फिर हम प्रत्येक के माध्यम से पुनरावृति करेंगे:
queryset = Product.objects.all() for each in queryset: do_something(each)
जबकि अगर हम iterator()
का उपयोग करते हैं, तो Django SQL कनेक्शन को खुला रखेगा और प्रत्येक रिकॉर्ड को पढ़ेगा, और अगला रिकॉर्ड पढ़ने से पहले do_something()
को कॉल करेगा:
queryset = Product.objects.all().iterator() for each in queryset: do_something(each)
Django प्रत्येक अनुरोध के लिए एक नया डेटाबेस कनेक्शन बनाता है और अनुरोध पूरा होने के बाद इसे बंद कर देता है। यह व्यवहार CONN_MAX_AGE
के कारण होता है, जिसका डिफ़ॉल्ट मान 0 है। लेकिन इसे कब तक सेट किया जाना चाहिए? यह आपकी साइट पर ट्रैफ़िक की मात्रा से निर्धारित होता है; वॉल्यूम जितना अधिक होगा, कनेक्शन बनाए रखने के लिए उतने ही अधिक सेकंड की आवश्यकता होगी। आमतौर पर कम संख्या से शुरू करने की सिफारिश की जाती है, जैसे कि 60।
आपको अपने अतिरिक्त विकल्पों को OPTIONS
में लपेटने की आवश्यकता है, जैसा कि में विस्तृत है
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'dashboard', 'USER': 'root', 'PASSWORD': 'root', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': { 'CONN_MAX_AGE': '60', } } }
क्वेरी एक्सप्रेशन एक मान या गणना को परिभाषित करते हैं जिसका उपयोग अपडेट, क्रिएट, फिल्टर, ऑर्डर बाय, एनोटेशन या एग्रीगेट ऑपरेशन में किया जा सकता है।
Django में आमतौर पर उपयोग की जाने वाली अंतर्निहित क्वेरी अभिव्यक्ति F अभिव्यक्ति है। आइए देखें कि यह कैसे काम करता है और उपयोगी हो सकता है।
नोट: ये भाव django.db.models.expressions
और django.db.models.aggregates
में परिभाषित हैं, लेकिन सुविधा के लिए, वे उपलब्ध हैं और आमतौर पर django.db.models
से आयात किए जाते हैं।
Django Queryset API में, मॉडल फ़ील्ड मानों को सीधे संदर्भित करने के लिए F()
अभिव्यक्तियों का उपयोग किया जाता है। यह आपको मॉडल फ़ील्ड मानों को संदर्भित करने और उन्हें डेटाबेस से और पायथन मेमोरी में लाने के बिना उन पर डेटाबेस क्रियाओं का संचालन करने की अनुमति देता है। इसके बजाय, Django एक SQL वाक्यांश बनाने के लिए F()
ऑब्जेक्ट को नियोजित करता है जो आवश्यक डेटाबेस गतिविधि को परिभाषित करता है।
उदाहरण के लिए, मान लें कि हम सभी उत्पादों की कीमत में 20% की वृद्धि करना चाहते हैं, तो कोड कुछ इस तरह दिखेगा:
products = Product.objects.all() for product in products: product.price *= 1.2 product.save()
हालांकि, अगर हम F()
का उपयोग करते हैं, तो हम इसे एक ही प्रश्न में निम्नानुसार कर सकते हैं:
from django.db.models import F Product.objects.update(price=F('price') * 1.2)
select_related()
और prefetch_related()
() का उपयोग करना Django डेटाबेस अनुरोधों की संख्या को कम करके आपके क्वेरीसेट को अनुकूलित करने के लिए select_related()
और प्रीफेच_संबंधित ( prefetch_related()
तर्क प्रदान करता है।
आधिकारिक Django दस्तावेज़ीकरण के अनुसार:
select_related()
विदेशी-कुंजी संबंधों का "अनुसरण करता है", अतिरिक्त संबंधित-वस्तु डेटा का चयन करते समय यह अपनी क्वेरी निष्पादित करता है।
prefetch_related()
प्रत्येक रिश्ते के लिए एक अलग लुकअप करता है, और पायथन में "जॉइनिंग" करता है।
select_related()
हम select_related()
का उपयोग तब करते हैं जब आइटम का चयन किया जाना एक एकल वस्तु है जिसका अर्थ है OneToOne
ForeignKey
बैकवर्ड OneToOne
फ़ील्ड।
आप एक एकल क्वेरी बनाने के लिए select_related()
का उपयोग कर सकते हैं जो एक-से-एक कनेक्शन के लिए एक ही उदाहरण के लिए सभी संबंधित ऑब्जेक्ट लौटाता है। जब क्वेरी की जाती है, select_related()
विदेशी-कुंजी संबंधों से कोई अतिरिक्त संबंधित-ऑब्जेक्ट डेटा पुनर्प्राप्त करता है।
select_related()
SQL जॉइन बनाकर काम करता है और SELECT
एक्सप्रेशन में संबंधित ऑब्जेक्ट के कॉलम को शामिल करता है। नतीजतन, select_related()
उसी डेटाबेस क्वेरी में संबंधित आइटम लौटाता है।
हालांकि select_related()
एक अधिक परिष्कृत क्वेरी उत्पन्न करता है, प्राप्त डेटा को कैश किया जाता है, इस प्रकार प्राप्त डेटा को संभालने के लिए किसी अतिरिक्त डेटाबेस अनुरोध की आवश्यकता नहीं होती है।
सिंटैक्स बस इस तरह दिखता है:
queryset = Tweet.objects.select_related('owner').all()
prefetch_related()
इसके विपरीत, prefetch_related()
का उपयोग कई-से-कई और कई-से-एक कनेक्शन के लिए किया जाता है। यह एक एकल क्वेरी उत्पन्न करता है जिसमें सभी मॉडल शामिल हैं और क्वेरी में फ़िल्टर दिए गए हैं।
सिंटैक्स बस इस तरह दिखता है:
Book.objects.prefetch_related('author').get(id=1).author.first_name
नोट: कई सारे रिश्तों को SQL का उपयोग करके नियंत्रित नहीं किया जाना चाहिए क्योंकि बड़ी तालिकाओं के साथ काम करते समय कई प्रदर्शन समस्याएँ प्रकट हो सकती हैं। यही कारण है कि prefetch_संबंधित विधि बड़े SQL जुड़ने से बचने के लिए पायथन के अंदर तालिकाओं में शामिल हो जाती है।
select_related()
prefetch_related()
बीच के अंतर के बारे में विस्तार से पढ़ें।
bulk_create()
और bulk_update()
) का उपयोग करना bulk_create()
एक ऐसा तरीका है जो एक क्वेरी के साथ डेटाबेस में वस्तुओं की प्रदान की गई सूची बनाता है। इसी तरह, bulk_update()
एक ऐसा तरीका है जो दिए गए मॉडल इंस्टेंस पर दिए गए फ़ील्ड को एक क्वेरी के साथ अपडेट करता है।
उदाहरण के लिए, यदि हमारे पास एक पोस्ट मॉडल है जैसा कि नीचे दिखाया गया है:
class Post(models.Model): title = models.CharField(max_length=300, unique=True) time = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title
अब, मान लें कि हम इस मॉडल में कई डेटा रिकॉर्ड जोड़ना चाहते हैं, तो हम इस तरह bulk_create()
का उपयोग कर सकते हैं:
#articles articles = [Post(title="Hello python"), Post(title="Hello django"), Post(title="Hello bulk")] #insert data Post.objects.bulk_create(articles)
और आउटपुट इस तरह दिखेगा:
>>> Post.objects.all() <QuerySet [<Post: Hello python>, <Post: Hello django>, <Post: Hello bulk>]>
और अगर हम डेटा को अपडेट करना चाहते हैं, तो हम इस तरह bulk_update()
का उपयोग कर सकते हैं:
update_queries = [] a = Post.objects.get(id=14) b = Post.objects.get(id=15) c = Post.objects.get(id=16) #set update value a.title="Hello python updated" b.title="Hello django updated" c.title="Hello bulk updated" #append update_queries.extend((a, b, c)) Post.objects.bulk_update(update_queries, ['title'])
और आउटपुट इस तरह दिखेगा:
>>> Post.objects.all() <QuerySet [<Post: Hello python updated>, <Post: Hello django updated>, <Post: Hello bulk updated>]>
इस लेख में, हमने डेटाबेस के प्रदर्शन को अनुकूलित करने, बाधाओं को कम करने और Django एप्लिकेशन में संसाधनों को बचाने के लिए युक्तियों को शामिल किया है।
मुझे आशा है कि आपको यह मददगार लगा। पढ़ते रहिये!