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

Django关联3个模型时如何用select_related/prefetch_related减少冗余查询

问题分析

冗余查询产生的原因:你当前仅通过select_related('kpi_id')关联了Kpis表,而Kpis模型关联的Domains表数据没有被预加载,每次访问t_k.kpi_id.domain_id.display_name时,Django都会对每个未缓存的domain_id发起一次单独的SQL查询,你观察到的10次额外查询就对应10个不同的domain_id记录。
你之前链式调用关联方法失败,大概率是没有指定正确的跨表关联路径,domain_id是Kpis模型的字段,不是TestsAndKpis的直接字段,不能单独作为关联参数传入。

解决方案

直接在select_related中通过双下划线__指定跨表关联路径,一次性关联Kpis和Domains两个关联表,通过一次JOIN查询拉取所有需要的数据,即可完全避免额外的N+1查询问题:

items = [
    {
        'kpi_type': t_k.type,
        'kpi_name': t_k.kpi_id.name,
        'kpi_display_name': t_k.kpi_id.display_name,
        'domain_display_name': t_k.kpi_id.domain_id.display_name
    }
    for t_k in TestsAndKpis.objects.filter(test_id=test_id).select_related('kpi_id__domain_id')
]
额外优化建议

如果你只需要上述几个返回字段,还可以用values()直接构造字典,省略ORM对象实例化的开销,性能会进一步提升:

from django.db.models import F

items = list(TestsAndKpis.objects.filter(test_id=test_id).values(
    kpi_type=F('type'),
    kpi_name=F('kpi_id__name'),
    kpi_display_name=F('kpi_id__display_name'),
    domain_display_name=F('kpi_id__domain_id__display_name')
))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 07:15:05