Django查询不足百万行数据库响应极慢,如何优化统计性能
问题核心原因分析
你当前的写法是把全表所有行数据加载到Django应用内存中,再用Python循环求和,1万条数据的情况下会产生大量的序列化、内存占用和CPU计算开销,这是耗时高的核心原因。
可选优化方案
1. 优先使用数据库聚合函数(改造成本最低,提升最明显)
直接用Django ORM的Sum聚合把计算逻辑下沉到数据库层面,不需要把全表数据拉到应用层,执行效率会提升数十倍,修改后的代码如下:
from django.db.models import Sum def test_view(request): total_count = Articles.objects.aggregate(total=Sum("words_count"))["total"] or 0 response = f'Total words : {total_count}' return HttpResponse(response)
- 优势:不需要修改表结构、不需要额外的定时任务,查询耗时基本可以控制在100ms以内,适合统计逻辑不需要高频调用的场景。
2. 增加字段索引
如果words_count字段没有建索引,给该字段增加普通索引,能够进一步提升数据库聚合的速度,执行迁移即可:
# 在Articles模型的words_count字段添加db_index属性 class Articles(models.Model): words_count = models.IntegerField(db_index=True, ...) # 其他字段省略
3. 缓存统计结果
如果这类统计的实时性要求不高,可以用Django自带的缓存框架缓存结果,避免每次请求都查数据库:
from django.core.cache import cache from django.db.models import Sum def test_view(request): total_count = cache.get("articles_total_words") if total_count is None: total_count = Articles.objects.aggregate(total=Sum("words_count"))["total"] or 0 # 缓存1小时,可根据业务要求调整过期时间 cache.set("articles_total_words", total_count, timeout=3600) response = f'Total words : {total_count}' return HttpResponse(response)
- 进阶方案:可以在新增、删除、修改文章记录的时候主动更新缓存,既保证统计的实时性,又不需要每次查库。
4. 专用统计表(也就是你提到的方案)
适合统计逻辑复杂、数据量达到百万级以上的场景,你可以用定时任务(比如Celery Beat、crontab)定期更新统计表,也可以用Django信号在文章数据变更的时候实时更新统计字段,查询的时候直接读单条记录,耗时基本在10ms级别。
方案选择建议
你现在只有1万条数据的规模,优先选择方案1+方案3的组合即可,改造成本极低,完全可以把请求耗时控制在200ms以内的合理范围,不需要一开始就新增统计表增加维护成本。
内容的提问来源于stack exchange,提问作者pythonize
相关产品推荐
相关产品推荐

