You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中prefetch_related未减少查询量的问题及优化方案

问题原因

你用了prefetch_related('m2m_model_set')但还是触发大量查询,核心原因是:values_list()会生成全新的QuerySet,Django不会复用预取的对象集合,而是每次循环都重新向数据库发起查询。也就是说,你预取的是完整的m2m_model对象,但调用all().values_list('field')时,Django会把这个操作当成独立查询,导致N+1查询问题(1次查MyModel,N次查每个MyModel对应的m2m_model)。

优化方案

方案1:复用预取对象,避免新查询

既然已经预取了完整的m2m_model对象,直接从对象里提取字段就行,不用调用values_list():

myList = []
qs = MyModel.objects.all().prefetch_related('m2m_model_set')
for model in qs:
    # 直接从预取的对象中取field值,不触发新查询
    k = [obj.field for obj in model.m2m_model_set.all()]
    myList.extend(k)

方案2:用Prefetch指定只预取需要的字段

如果不想加载完整的m2m_model对象,可以用Prefetch配合only(),只预取需要的field字段,减少内存占用同时避免额外查询:

from django.db.models import Prefetch

myList = []
# 只预取m2m_model的field字段
prefetch = Prefetch('m2m_model_set', queryset=M2MModel.objects.only('field'))
qs = MyModel.objects.all().prefetch_related(prefetch)
for model in qs:
    k = [obj.field for obj in model.m2m_model_set.all()]
    myList.extend(k)

方案3:直接从关联模型反向查询,一次搞定

如果不需要MyModel的其他数据,直接从m2m_model模型出发,通过反向关联过滤,一次查询就能拿到所有需要的field值:

# 假设M2MModel是你的多对多模型,my_model是关联MyModel的外键字段(自动生成或自定义的)
myList = list(M2MModel.objects.filter(my_model__isnull=False).values_list('field', flat=True))

这里flat=True会让values_list返回一维列表,连循环都省了。


内容的提问来源于stack exchange,提问作者Kodeeo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:48:14