2012-01-18 7 views
7

में एक ही वस्तु के लिए कई संदर्भ से बचना हम अत्यधिक परस्पर डेटा के साथ किसी ऐप्लिकेशन है, अर्थात कई मामलों में जहां दो वस्तुओं एक रिश्ते के माध्यम से एक ही वस्तु का उल्लेख हो सकता है देखते हैं। जहां तक ​​मैं कह सकता हूं, Django पहले से प्राप्त किए गए ऑब्जेक्ट के संदर्भ को वापस करने का कोई प्रयास नहीं करता है यदि आप इसे एक अलग, पहले अपरिहार्य रिश्ते के माध्यम से लाने का प्रयास करते हैं।Django ORM

उदाहरण के लिए:

class Customer(Model): 
    firstName = CharField(max_length = 64) 
    lastName = CharField(max_length = 64) 

class Order(Model): 
    customer = ForeignKey(Customer, related_name = "orders") 

तो मान हम एक ही ग्राहक जो डीबी में दो आदेश है है:

order1, order2 = Order.objects.all() 
print order1.customer # (1) One DB fetch here 
print order2.customer # (2) Another DB fetch here 
print order1.customer == order2.customer # (3) True, because PKs match 
print id(order1.customer) == id(order2.customer) # (4) False, not the same object 

आप अत्यधिक परस्पर डेटा है, तो किस हद तक के संबंधों तक पहुँचने के लिए आपके ऑब्जेक्ट्स का परिणाम उसी डेटा के लिए डीबी के बार-बार पूछताछ में होता है और एक समस्या बन जाती है।

हम भी iOS के लिए और CoreData के बारे में अच्छा चीजों में से एक यह है कि यह संदर्भ का कहना है, ताकि किसी दिए गए संदर्भ में जब उस खास मॉडल की ही कभी एक उदाहरण है कार्यक्रम। ऊपर दिए गए उदाहरण में, कोरडाटा ने दूसरे फ्रेच (2) पर नहीं किया होगा, क्योंकि यह पहले से ही स्मृति में ग्राहक का उपयोग कर रिश्ते को हल कर लेगा।

यहां तक ​​कि अगर लाइन (2) एक और डीबी लाने (जैसे print Order.objects.exclude(pk = order1.pk).get(customer = order1.customer)) के लिए मजबूर करने के लिए बनाया गया एक नकली उदाहरण के साथ बदल दिया गया था, CoreData एहसास होता है कि इस बात का परिणाम दूसरे स्मृति में एक मॉडल का संकल्प लाने और मौजूदा मॉडल के बजाय वापसी एक नया (यानी (4) कोरडाटा में सच प्रिंट करेगा क्योंकि वे वास्तव में एक ही वस्तु होगी)।

Django के इस व्यवहार से बचाव करने के लिए, हम थोड़े उनके (type, pk) द्वारा स्मृति में कैश मॉडल करने की कोशिश और उसके बाद _id प्रत्यय के साथ संबंधों की जांच करने के लिए उन्हें कैश से पहले आँख बंद करके मारने से खींचने की कोशिश करने के लिए यह सब भयानक सामान लिख रहे हैं एक और fetch के साथ डीबी। यह डीबी थ्रूपुट पर काट रहा है लेकिन वास्तव में भंगुर महसूस करता है और यदि समस्याएं कुछ जटिल ढांचे या मिडलवेयर में गलती से होती हैं जो हम नियंत्रित नहीं करते हैं तो सामान्य संबंधों के माध्यम से सामान्य संबंध लुकअप होते हैं।

वहाँ Django में मदद करने के लिए इस समस्या से बचने वहाँ किसी भी सर्वोत्तम प्रथाओं या चौखटे हैं? क्या किसी ने डीजेगो के ओआरएम में दोहराए गए लुकअप से बचने के लिए किसी भी प्रकार के धागे-स्थानीय संदर्भ को स्थापित करने का प्रयास किया है और एक ही डीबी मॉडल में मैपिंग के कई इन-मेमोरी उदाहरण हैं?

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

उत्तर

2

डेविड क्रेमर की django-id-mapper यह करने के लिए एक प्रयास है।

+0

धन्यवाद डैनियल - यह एक scarily लंबे समय में अपडेट नहीं किया गया है, लेकिन मैं इसे जाने दे और देखें कि क्या यह अभी भी काम करता है हूँ। – glenc

+0

तो थोड़ा सा शोध करने के बाद, ऐसा लगता है कि यह काम काम कर सकता है, क्योंकि जब आप (टाइप, पीके) कैश हिट करते हैं तो नए लोगों के बजाय कैश किए गए उदाहरणों को वापस करने के लिए यह मूल रूप से मेटाक्लास '__call__' को फिर से हुक करता है। यह अभी भी पूरी तरह से क्वेरी कैशिंग पर निर्भर करता है, क्योंकि यह विदेशी कुंजी के उप-वर्ग प्रदान नहीं करता है जो वास्तविक प्रश्न को फायर करने से पहले कैश किए गए उदाहरणों को वापस करने का तरीका जानता है - इसलिए 100% आदर्श नहीं। शायद इस विदेशीकी को एक जिथब कांटा में लागू करेगा और परिणामों के साथ यहां वापस पोस्ट करेगा। – glenc

1

वहाँ एक प्रासंगिक DB optimization page Django दस्तावेज में है; मूल रूप से कॉलबेल कैश नहीं किए जाते हैं, लेकिन विशेषताएं हैं (बाद में कॉल order1.customer डेटाबेस को हिट नहीं करते हैं), हालांकि केवल उनके ऑब्जेक्ट स्वामी के संदर्भ में (इसलिए, विभिन्न ऑर्डर के बीच साझा नहीं करना)।

कैश

आप कहते हैं के रूप में, अपनी समस्या को हल करने के लिए एक तरह से उपयोग कर एक डेटाबेस कैश का प्रयोग है। हम बिटबकेट के johnny cache का उपयोग करते हैं, जो लगभग पूरी तरह से पारदर्शी है; एक और अच्छा पारदर्शी एक मोज़िला cache machine है। आपके पास कम पारदर्शी कैशिंग सिस्टम भी पसंद है जो वास्तव में बिल को बेहतर ढंग से फिट कर सकता है, कृपया djangopackages/caching देखें।

एक कैश जोड़ा जा रहा है वास्तव में बहुत फायदेमंद विभिन्न अनुरोधों को एक ही ग्राहक को फिर से उपयोग करने की आवश्यकता है, तो हो सकता है; लेकिन कृपया read this जो आपके लिखने/पढ़ने के पैटर्न इस तरह के कैशिंग सिस्टम सूट के माध्यम से सोचने के लिए सबसे पारदर्शी कैश सिस्टम पर लागू होता है।

अनुरोध

अपने सटीक उदाहरण के लिए एक और दृष्टिकोण के अनुकूलन select_related उपयोग करने के लिए है।

order1, order2 = Order.objects.all().select_related('customer') 

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

संबंधित मुद्दे