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

优化拥有2000万条记录的Django站点MySQL总记录数统计速度

Django大数据量下COUNT(DISTINCT)性能优化方案
  • 改用覆盖索引
    你当前的查询是基于多个过滤条件统计唯一OGRN/OGRNIP的数量,普通单字段索引可能无法满足需求。建议创建包含所有过滤字段+目标唯一字段的联合覆盖索引,让数据库无需回表查询,直接从索引中完成统计计算。
    示例(以公司表为例,按过滤条件的筛选力度从高到低排序字段):

    CREATE INDEX idx_company_filter_ogrn ON company_table (email_field, okved_field, capital_field, OGRN);
    

    注意:联合索引的字段顺序很关键,把过滤时能筛掉更多数据的字段放在前面。

  • 允许近似统计的话,换用近似方案
    如果业务场景不需要绝对精确的数值,可以用数据库自带的近似统计功能:

    • MySQL:通过EXPLAIN语句的rows字段估算结果数;
    • PostgreSQL:查询pg_stat_user_tables表的n_live_tup字段获取近似行数;
      也可以用Redis缓存近似值,定期更新,前端显示时标注“约XX条”,能把查询耗时降到毫秒级。
  • 预计算统计值(离线聚合)
    对实时性要求不高的场景,用定时任务(比如Django的Celery+Beat)定期跑统计任务,把结果存在单独的统计表或Redis中:

    1. 每天凌晨执行全量统计,覆盖所有常用过滤条件组合的结果;
    2. 或者做增量更新:每次新增/删除数据时,同步更新对应统计值的计数;
      查询时直接读取预计算好的值,完全避免对大表的实时扫描。
  • 优化查询语句逻辑

    • 检查WHERE条件里的字段是否存在隐式类型转换(比如字符串字段用数字匹配),这会直接导致索引失效;
    • 清理from_clause里不必要的关联表,减少数据扫描范围;
    • 把COUNT(DISTINCT)改成子查询先去重再计数,部分数据库优化器对这种写法的处理效率更高:
      SELECT COUNT(*) FROM (SELECT DISTINCT cs.OGRN FROM ... WHERE ...) AS tmp;
      
  • 数据库层面的进阶优化

    • 分区表:将大表按时间、地区或核心过滤字段分区,查询时只扫描符合条件的分区,大幅减少扫描的数据量;
    • 调整数据库配置:加大内存让更多数据缓存到内存中,优化查询缓存(如果适用);如果业务允许,MyISAM引擎的COUNT(*)性能比InnoDB好,但要注意它不支持事务和行级锁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:02:33