2013-05-30 3 views
1

Предположим, что у меня есть два связанных моделейДжанго - эффективность использования связанных полей модели

class Foo(models.Model): 
    value = models.FloatField() 

class Bar(models.Model): 
    multiplier = models.FloatField() 
    foo = models.ForeignKey(Foo, related_name="bars") 

    def multiply(self): 
     return self.foo.value * self.multiplier 

Экземпляр Foo часто будет иметь много экземпляров бар, но некоторую информацию, которая имеет отношение к расчету, что бар делает хранится в Foo (потому что это одно и то же для всех случаев, связанных Bars)

проблема заключается в том, когда я делаю что-то вроде этого:

foo = Foo.objects.latest() 
[x.multiply() for x in foo.bars.all()] 

он заканчивает заганяют потому что каждый объект Bar в foo.bars.all() запрашивает базу данных для объекта Foo. Итак, если у меня есть 10 баров, я повлечет за собой 11 запросов к базе данных (1 для получения набора запросов с 10 барами и 1 для каждого объекта Bar, возвращающегося назад, чтобы получить self.foo.value). Использование select_related(), похоже, не помогает.

Мои вопросы: 1) Правильно ли я считаю, что memcached (например, Johnny Cache, Cache Machine) решит эту проблему? 2) Есть ли способ разработки отношений объектов, которые могут сделать команду более эффективной без кеша?

+0

Почему это было 11 запросов? это всего лишь 2 вопроса. – karthikr

+0

К сожалению, это была опечатка, должна быть [x.multiply() для x в foo.bars.all()]. Поскольку multiply() требует значения, которое хранится в foo, каждый вызов функции multiply() должен извлекать foo. – hgcrpd

ответ

3

Именно такая ситуация, для которой были созданы select_related и prefetch_related. Когда вы запрашиваете эти данные, ORM Django использует один из двух методов, чтобы избежать избыточных запросов к базе данных: следующие отношения через JOINs (select_related) или предварительное кэширование отношений «один ко многим/много-ко-многим» в их QuerySets.

# Hits the database 
foo = Foo.objects.prefetch_related('bars').latest() 

# Doesn't hit the database 
[x.value for x in foo.bars.all()] 
+0

prefetch_related() был он. Благодаря! – hgcrpd

Смежные вопросы