【发布时间】:2024-04-15 02:35:01
【问题描述】:
m = MyModel.objects.all().only("colA", "colB").prefetch_related("manyToManyField")
for mm in m:
print(mm.id)
list(mm.manyToManyField.values_list('id', flat=True))
此代码执行时间过长。
这几乎不需要时间(循环中没有引用 manyToManyField):
m = MyModel.objects.all().only("colA", "colB").prefetch_related("manyToManyField")
for mm in m:
print(mm.id)
这几乎与第一次精确相同
m = MyModel.objects.all().only("colA", "colB")
for mm in m:
print(mm.id)
list(mm.manyToManyField.values_list('id', flat=True))
这让我觉得.prefetch_related("manyToManyField") 没用,它实际上并没有获取任何东西,list(mm.manyToManyField.values_list('id', flat=True)) 在每个周期都会访问数据库。
为什么会这样?如何强制从多对多字段中预取?
我尝试删除 list(),但随后 mm.manyToManyField.all().values_list 给了我一个不是 JSON 可序列化的查询集(不,我不想安装 rest 框架)。
还尝试了list(mm.manyToManyField.all().values_list) 和list():仍然非常缓慢。
【问题讨论】:
-
使用
.values_list确实不会提高性能,因为所有不同于.all()的查询都会再次访问数据库。 -
也试过list(manyToManyField.all().values_list(...)),还是一样的问题。现在更新问题...
-
当然,因为您再次进行了与
.prefetch_related(..)的查询不同的查询,因此它必须对数据库进行另一次查询。 -
这是一个不同的查询?我正在查询 mm 对象,它应该预先加载了 m2m 字段。
-
哦,你的意思是我应该只调用 .all() 然后手动做值列表,而不是使用 Django 函数做列表?
标签: python django django-orm