Django prefetch_related似乎无法按预期运行

时间:2019-08-07 10:49:21

标签: django django-models django-queryset

描述

有一个Foo模型,其中有一个ForeignKey字段bar

class Foo(models.Model):
  ...
  bar = models.ManyToManyField('bar.Bar', related_name='some_bar')
  ...

另外Foo具有get_config()方法,该方法返回其包含bar的字段,如:

def get_config(self):
  return {
    ...
    'bar': map(lambda x: x.get_config(), self.bar.all())
    ...

现在数据库中有10,000行Foo。也有一些Bar行。

尝试检索大约10,000 Foo的数据,包括嵌套的Bar数据:

query = Foo.objects.all().prefetch_related('bar')
return [obj.get_config() for obj in query]

问题

查询执行大约6秒钟。如果没有bar字段-仅400毫秒。

预取似乎不能完全起作用bar.get_config()似乎在每个迭代步骤中都命中数据库。应该只加载一次所有Bar对象一次,然后从该条查询中获取配置以填充每个foo配置。

想法

如果在iterator()循环中使用for,则通话几乎停顿并花费数十秒:[obj.get_config() for obj in query.iterator()]

1 个答案:

答案 0 :(得分:0)

prefetch_related正在工作。 Django使用包含WHERE子句和所有Bar中的ids的单个SELECT预取Foo。这个具有10k id的SELECT比10k SELECTS快得多,但比没有过滤器的单个SELECT慢得多。