جانغو ORM: تحسين الاستفسارات التي تنطوي على العديد من لكثير العلاقات

StackOverflow https://stackoverflow.com/questions/1642092

سؤال

ولدي هيكل نموذج التالية:

class Container(models.Model):
    pass

class Generic(models.Model):
    name = models.CharacterField(unique=True)
    cont = models.ManyToManyField(Container, null=True)
    # It is possible to have a Generic object not associated with any container, 
    # thats why null=True

class Specific1(Generic):
    ...

class Specific2(Generic):
    ...

...

class SpecificN(Generic):
    ...

ويقول، ولست بحاجة إلى استرداد كافة النماذج Specific من نوع، والتي لها علاقة مع حاوية معينة.

ووSQL لذلك هو أكثر أو أقل تافهة، ولكن ليس هذا هو السؤال. للأسف، وأنا لا خبرة كبيرة في العمل مع ORMs (ORM جانغو على وجه الخصوص)، ولذا فإنني قد يكون في عداد المفقودين نمط هنا.

عند ذلك بطريقة القوة الغاشمة، -

c = Container.objects.get(name='somename') # this gets me the container
items = c.generic_set.all() 
# this gets me all Generic objects, that are related to the container
# Now what? I need to get to the actual Specific objects, so I need to somehow
# get the type of the underlying Specific object and get it
for item in items:
    spec = getattr(item, item.get_my_specific_type())

وهذا يؤدي إلى طن من الزيارات ديسيبل (واحد لكل سجل عام، التي تتعلق حاوية)، لذلك من الواضح أن هذا ليس طريقة للقيام بذلك. الآن، يمكن، ربما، أن يتم ذلك عن طريق الحصول على SpecificX الكائنات مباشرة:

s = Specific1.objects.filter(cont__name='somename')
# This gets me all Specific1 objects for the specified container
...
# do it for every Specific type

وبهذه الطريقة سيتم ضرب ديسيبل مرة واحدة لكل نوع خاص (مقبولة، أعتقد).

وأنا أعلم، أن .select_related () لا يعمل مع العلاقات M2M، لذلك فإنه ليس من الكثير من المساعدة هنا.

لمجددا، والنتيجة النهائية يجب أن تكون مجموعة من الكائنات SpecificX (وليس عام).

هل كانت مفيدة؟

المحلول

وأعتقد أنك قد أوجز بالفعل اثنين من الاحتمالات سهلة. إما أن تفعل استعلام مرشح واحد ضد عام ثم يلقي كل بند من النوع الفرعي في النوعية (نتائج البحث في ن + 1 الاستفسارات، حيث n هو عدد العناصر عاد)، أو إجراء استعلام منفصل ضد كل جدول معين (نتائج البحث في ك استفسار، حيث k هو عدد من أنواع معينة).

وانها فعلا يستحق المقارنة لمعرفة أي من هذه أسرع في الواقع. والثاني يبدو أفضل لأنه (ربما) أقل الاستفسارات، ولكن كل واحدة من تلك الاستفسارات لديها لأداء الانضمام مع جدول المتوسطة M2M. في الحالة الأولى أنت فقط لا احد انضمام الاستعلام، ثم العديد من تلك بسيطة. بعض الخلفيات قاعدة بيانات أداء أفضل مع الكثير من الاستفسارات صغيرة من أقل منها، أكثر تعقيدا.

إذا والثاني هو في الواقع أسرع بشكل ملحوظ لحالة استخدامك، وكنت على استعداد للقيام ببعض العمل الإضافي لتنظيف الشفرة الخاصة بك، يجب أن يكون من الممكن أن يكتب طريقة مدير مخصص لنموذج عام أن "عمليات الجلب، قبل "جميع البيانات النوع الفرعي من الجداول المحددة ذات الصلة لمجموعة طلبات البحث معين، باستخدام استعلام واحد فقط لكل جدول فرعي. على غرار كيف هذا المقتطف يحسن المفاتيح الخارجية العامة مع الجلب المسبق بالجملة. هذا من شأنه أن تعطيك نفس الاستفسارات كخيار الثاني، مع بناء الجملة مجفف الخيار الأول.

نصائح أخرى

وليس على إجابة كاملة ولكن يمكنك تجنب عدد كبير من الزيارات من خلال ذلك

items= list(items)
for item in items:
    spec = getattr(item, item.get_my_specific_type())

وبدلا من هذا:

for item in items:
    spec = getattr(item, item.get_my_specific_type())

والواقع، من خلال اجبار المدلى بها إلى قائمة الثعبان، لإجبار مكتب إدارة السجلات جانغو لتحميل كافة العناصر في مجموعة طلبات البحث الخاصة بك. ثم يفعل ذلك في استعلام واحد.

وأنا stubmled بطريق الخطأ على آخر التالية، والتي يجيب حد كبير سؤالك:

http://lazypython.blogspot.com/2008 /11/timeline-view-in-django.html

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top