سؤال

لدي نموذج يسمى Valor. فالور لديه روبوت. أنا استعلام مثل هذا:

Valor.objects.filter(robot=r).reverse()[0]

للحصول على آخر Valor Robot R. Valor.Objects.filter (Robot = R) .count () حوالي 200000 والحصول على العناصر الأخيرة يستغرق حوالي 4 ثوان في جهاز الكمبيوتر الخاص بي.

كيف يمكنني تسريعه؟ أنا استعلم بالطريقة الخطأ؟

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

المحلول

يبدو أنه يبدو أن مجموعة البيانات الخاصة بك ستكون كبيرة بما يكفي، قد ترغب في إنهاء الأشياء قليلا. هل حاولت تتبع كائن Valor آخر في كائن الروبوت؟

class Robot(models.Model):
    # ...
    last_valor = models.ForeignKey('Valor', null=True, blank=True)

ثم استخدام post_save. الإشارة لجعل التحديث.

from django.db.models.signals import post_save

def record_last_valor(sender, **kwargs):
    if kwargs.get('created', False):
        instance = kwargs.get('instance')
        instance.robot.last_valor = instance

post_save.connect(record_last_valor, sender=Valor)

ستدفع تكلفة معاملة DB إضافية عند إنشاء كائنات Valor، لكن البحث last_valor سوف يخشق بسرعة. العب معها ومعرفة ما إذا كانت المفاضلة يستحق كل هذا العناء لتطبيقك.

نصائح أخرى

سيكون بناء جملة MySQL الأمثل لهذه المشكلة شيئا على غرار:

SELECT * FROM table WHERE x=y ORDER BY z DESC LIMIT 1

ما يعادل DJANGO هذا هو:

Valor.objects.filter(robot=r).order_by('-id')[:1][0]

لاحظ كيف يستخدم هذا الحل DJANGO تشريح طريقة للحد من queryset قبل تجميع قائمة الكائنات.

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

SELECT * FROM valor v WHERE v.robot_id = [robot_id] ORDER BY id DESC LIMIT 1;

هل هذا بطيء؟ إذا كان الأمر كذلك، فقم بإجراء RDBMS (MySQL؟) شرح خطة الاستعلام لك. سيخبرك هذا إذا كان الأمر يقوم بمسح طاولة كاملة، والتي من الواضح أنك لا تريدها مع جدول كبير. قد تقوم أيضا بتحرير سؤالك وتضمين مخطط valor الجدول بالنسبة لنا أن نرى.

أيضا، يمكنك رؤية SQL التي تولد django عن طريق القيام بذلك (باستخدام مجموعة الاستعلام المقدمة من Peter Rowell):

qs = Valor.objects.filter(robot=r).order_by('-id')[0]
print qs.query

تأكد من أن SQL يشبه الاستعلام "RAW" الذي أرسلته أعلاه. يمكنك أيضا جعل RDBMS الخاص بك شرح خطة الاستعلام إليك.

حسنا، ليس هناك أي جملة لأمر أمر، لذلك أتساءل عن ما تعنيه "الأخير". على افتراض أنك تعني "آخر إضافته"،

Valor.objects.filter(robot=r).order_by('-id')[0]

قد تفعل المهمة لك.

Django 1.6 يقدم .First () و .LAST ():

https:/docs.djangoproject.com/en/1.6/ref/models/querys/#Last.

لذلك يمكنك ببساطة القيام:

Valor.objects.filter(robot=r).last()

سريع جدا يجب أن يكون أيضا:

qs = Valor.objects.filter(robot=r) # <-- it doesn't hit the database
count = qs.count()                 # <-- first hit the database, compute a count
last_item = qs[ count-1 ]          # <-- second hit the database, get specified rownum

لذلك، في الممارسة العملية، يمكنك تنفيذ استعلامات SQL فقط؛)

هل هناك بند الحد في Django؟ بهذه الطريقة يمكنك الحصول على DB، ببساطة إرجاع سجل واحد.

mysql.

 select * from table where x = y limit 1

خادم قاعدة البيانات

 select top 1 * from table where x = y

وحي

 select * from table where x = y and rownum = 1

أدرك أن هذا لا يترجم إلى django، لكن شخص ما يمكن أن يعود وتنظيف هذا الأمر.

الطريقة الصحيحة للقيام بذلك، هي استخدام أحدث طريقة QuerySet الأخيرة () وإطعامها أيهما العمود (اسم الحقل) يجب أن فرز حسب. العيب هو أنه يمكن فقط الفرز حسب عمود DB واحد.

يبدو التنفيذ الحالي هكذا ويتم تحسينه بنفس معنى اقتراح @ آرون.

def latest(self, field_name=None):
    """
    Returns the latest object, according to the model's 'get_latest_by'
    option or optional given field_name.
    """
    latest_by = field_name or self.model._meta.get_latest_by
    assert bool(latest_by), "latest() requires either a field_name parameter or 'get_latest_by' in the model"
    assert self.query.can_filter(), \
            "Cannot change a query once a slice has been taken."
    obj = self._clone()
    obj.query.set_limits(high=1)
    obj.query.clear_ordering()
    obj.query.add_ordering('-%s' % latest_by)
    return obj.get()
Model_Name.objects.first()

// للحصول على العنصر الأول

Model_name.objects.last()

// للحصول على آخر ()

في حالتي الأخيرة لا يعمل لأن هناك صف واحد فقط في قاعدة البيانات قد يساعدك بالكامل بالنسبة لك أيضا :)

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