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

Django 1.8复杂查询优化求助:耗时36秒无改善

优化Django ORM慢查询的解决方案

我之前也碰到过类似的Django ORM查询性能坑,你的核心问题是当前查询生成了低效的嵌套子查询,再加上可能缺失关键索引,才导致count操作耗时飙升。下面是具体的优化步骤:

1. 重构查询,用JOIN替代IN子查询

你原来的代码先查询Job的pk列表,再用job__in做子查询,这种方式会让数据库先执行子查询再匹配Candidate,大数据量下效率极低。直接通过关联字段过滤,Django会生成更高效的JOIN语句:

# 先获取当前用户对应的Employee对象(无需先提取pk)
emp = Employee.objects.filter(user=self.request.user, firm=obj).first()
if not emp:
    candidate_count = 0
else:
    # 直接通过Job的关联字段过滤Candidate,避免子查询
    _candidates = Candidate.objects.filter(
        Q(job__hiring_manager=emp) | Q(job__followers=emp),
        apply_date__range=[date_initial, date_end]
    ).order_by('-apply_date')
    candidate_count = _candidates.count()

这样生成的SQL会用JOIN替代IN子查询,数据库优化器能更好地利用索引加速查询。

2. 检查并添加关键索引

慢查询90%以上的原因是索引缺失,针对你的场景,需要确保以下索引存在:

  • Job表:hiring_manager_id的索引(Django外键默认会自动创建,可通过数据库工具确认)
  • 多对多表combo_job_followers:user_id和job_id的联合索引(Django自动生成的多对多中间表默认会有,但自定义中间表需要手动添加)
  • Candidate表:job_id和apply_date的联合索引(这是核心!你的查询同时过滤这两个字段,联合索引能让数据库直接定位符合条件的记录)

在Candidate模型中添加联合索引的示例:

class Candidate(models.Model):
    job = models.ForeignKey(Job, on_delete=models.CASCADE)
    apply_date = models.DateTimeField()
    # 其他字段...

    class Meta:
        indexes = [
            models.Index(fields=['job', 'apply_date'], name='candidate_job_apply_date_idx'),
        ]

3. 用explain()分析查询计划

调整后可以用Django的explain()方法查看查询计划,确认索引是否被正确使用:

print(_candidates.explain(verbose=True))

如果输出中出现Using index或Using where; Using index,说明索引生效了;如果出现Using filesort或Using temporary,则需要进一步调整索引或查询语句。

4. 额外优化点

  • 避免不必要的中间变量:原代码中的job_list完全可以省略,直接通过关联字段过滤
  • 如果apply_date的范围很大,可以考虑分批次统计,但你的场景下优先优化索引和查询结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 08:32:55