【问题标题】:Django - Optimize queries with select_related()Django - 使用 select_related() 优化查询
【发布时间】:2017-05-25 04:06:08
【问题描述】:

我有以下型号。

class Car(models.Model):
    owner = models.ForeignKey('Driver')

class Country(models.Model)
    name = models.CharField(max_length=255)

class Driver(models.Model):
    name = models.CharField(max_length=255)
    age = models.IntegerField()
    country = models.ForeignKey('Country')

我想选择拥有汽车的司机的姓名。

Car.objects.all().values('owner__name')

我是否需要使用 select_related() 方法来避免每个对象的连接,或者它是多余的,因为隐含了 values() 方法?

Car.objects.all().select_related('owner').values('owner__name')

同样,这一次,我想要司机拥有汽车的国家/地区的名称。哪个最好?

Car.objects.all().values('owner__country__name')
Car.objects.all().select_related('owner', 'country').values('owner__country__name')
Car.objects.all().select_related('owner__country').values('owner__country__name')

【问题讨论】:

  • 最后一部分我假设你想要Driver.objects.filter(car__isnull=False,...),但你的问题有点宽泛,你应该把它限制在关于隐式连接的第一个问题
  • 谢谢,我编辑了这个问题以缩小使用 select_related() 的范围。

标签: django django-queryset django-select-related


【解决方案1】:

首先,您的示例中所有出现的.all() 都可以删除; manager (.objects) 已经拥有了 QuerySet 的几乎所有方法,除了.delete()

.select_related 仅在您的最终查询返回 模型实例 时才有用;然后,每个实例的所有外键都会被预加载。

但是,如果您使用.values,您将获得字典,并且没有要预加载的外键属性。所以在这种情况下不应该使用它。

当您执行.values('owner__name') 时,Django 已经看到它需要加入车主和汽车,不会进行额外的查询。

在最后一个你想要国家,所以使用 Country.objects:

Country.objects.filter(driver__car__isnull=False).values('name')

【讨论】:

  • 感谢您的反馈。但即使使用 dict,我们也可以想象要迭代每个元素,Django 可以在数据库中进行新的连接查询。这就是为什么我想确保在这种情况下选择相关没有用。
猜你喜欢
  • 2020-08-02
  • 2022-01-08
  • 2018-11-08
  • 2019-07-21
  • 2011-10-08
  • 2012-03-19
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
相关资源
最近更新 更多