Django 在外键上正确使用 select_related 或 prefetch_related

标签 django optimization

我想弄清楚如何使用 select_relatedprefetch_related从外键的另一端优化查询。例如:

假设我有一些模型,例如:

class Product(models.Model):
    name = models.CharField(max_length=50)

class ProductImage(models.Model):
    image = models.ImageField(upload_to="images")
    product = models.ForeignKey("myapp.Product", related_name="product_images")

如果我想打印所有 ProductImage ,我必须遍历所有产品,然后对于每个产品,遍历所有产品图像。但是,这会产生 O(n * m) 次数据库查询。
for product in Product.objects.all():
    print product.product_images.all()

我想知道是否有办法利用 select_relatedprefetch_related将这种查找减少到一两个查询。

正如 Django 所记录的,我可以得到 select_related当我选择 ProductImage 时工作.如您所见,添加 select_related创建到产品表的 JOIN。
>>> ProductImage.objects.all().query.sql_with_params()
(u'SELECT "myapp_productimage"."id",  ...  FROM "myapp_productimage" .... 

>>> ProductImage.objects.select_related('product').query.sql_with_params()
(u'SELECT "myapp_productimage"."id", ...   FROM "myapp_productimage" LEFT OUTER JOIN ....

但是,我如何完成相反的操作?例如,我如何查询所有 Product s 并让它在 ProductImage 上加入?执行以下操作似乎不起作用。
Product.objects.select_related('product_images').query.sql_with_params()

在 Django 中可能有这样的事情吗?

感谢您的考虑。

最佳答案

这正是prefetch_related做。

Product.objects.prefetch_related('product_images')

但是,使用 query.sql_with_params() 毫无意义。对此进行诊断:prefetch_related做了两个查询,第二个不会出现在那里。您应该使用 django.db.connection.queries检查 Django 正在执行的查询,或者甚至更好地使用 Django 调试工具栏向您展示。

关于Django 在外键上正确使用 select_related 或 prefetch_related,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22734475/

相关文章:

Django 将已知的确切字符串作为 url 参数传递

python - Django:没有默认值的不可空字段

c - 如何删除 for 语句中方括号内的添加

c++ - 显式类型转换与使用类型规则

json - 为什么在 "warming up"之后解码 JSON 更快?

javascript - 将js变量传递给django View

python - 在我的 Django 代码中获取 KeyError

django - 使特定缓存无效

mysql 优化存储过程插入

optimization - 在 Mathematica 中优化内循环计算