如何优化Django查询结构或正确使用prefetch_related?附场景代码
优化查询结构与反向关联过滤方案
直接优化过滤逻辑(替代两次查询)
你当前的写法会触发两次数据库查询:第一次获取符合条件的document ID列表,第二次根据ID筛选Document。利用Django的反向关联查询,可以把这两步合并为一次高效查询:
qs = Document.objects.filter(rows__item=item_id).distinct()
- 这里的
rows是DocumentRows中document字段定义的related_name,通过rows__item直接关联到DocumentRows的item字段进行过滤 - 添加
.distinct()是为了避免同一个Document被多次返回(因为一个Document可能对应多个符合item=item_id的DocumentRows)
预取关联的DocumentRows数据(使用prefetch_related)
如果后续需要访问每个Document对应的符合条件的DocumentRows条目,可以用Prefetch对象配合prefetch_related,避免N+1查询问题:
from django.db.models import Prefetch # 先定义过滤后的DocumentRows查询集 filtered_rows = DocumentRows.objects.filter(item=item_id) # 预取指定条件的关联数据,同时过滤Document qs = Document.objects.filter(rows__item=item_id).distinct().prefetch_related( Prefetch('rows', queryset=filtered_rows, to_attr='filtered_rows') )
之后访问document.filtered_rows就能直接拿到该文档下符合item=item_id的所有DocumentRows,无需额外查询。
为什么不用原来的写法?
原代码的values_list + id__in会触发两次查询,且当数据量较大时,ID列表会占用额外内存,合并后的查询利用数据库的JOIN操作,效率更高,也更符合Django ORM的最佳实践。
内容的提问来源于stack exchange,提问作者Ranu Vijay
相关产品推荐
相关产品推荐

