如何提升MySQL千万级大表Count(*)查询效率?借助Redis或元数据表实现实时统计?

2026-05-20 13:270阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计870个文字,预计阅读时间需要4分钟。

如何提升MySQL千万级大表Count(*)查询效率?借助Redis或元数据表实现实时统计?

由于InnoDB引擎下默认使用COUNT(*)走全表扫描(即使有主键),不进行二级索引优化,也无法利用查询缓存(MySQL 8.0已移除),当表行数超过1000万、QPS较高时,单次COUNT(*)操作可能耗时2-5秒,甚至更容易阻塞其他DML操作。

用 Redis 做实时计数的实操要点

适合写多读少、允许短暂误差(秒级)的场景,比如「当前在线用户数」「文章总浏览量」。关键不是存总数,而是控制好增减时机和原子性。

  • INCRBYDECRBY 必须和业务 SQL 在同一事务中触发 —— 但 Redis 本身不参与 MySQL 事务,所以实际要靠应用层双写 + 补偿:先更新 MySQL,再 INCRBY;失败则记录日志,由后台任务重试
  • 不要用 GET + SET 模拟原子增减,会丢数据;必须用 INCRBY
  • 为防 Redis 宕机导致计数丢失,建议每天凌晨用 SELECT COUNT(*) FROM t 全量校准一次,写入 SET t:count:backup 作为兜底值
  • 如果业务有「软删除」,记得在删除逻辑里同步 DECRBY 1;硬删除则通常已含该逻辑

用元数据表替代 COUNT(*) 的落地方式

比 Redis 更可靠,适合要求强一致的场景,比如「会员总人数」「待审核订单数」。本质是把聚合结果物化成一行一列的普通表。

阅读全文
标签:MysqlRedisred

本文共计870个文字,预计阅读时间需要4分钟。

如何提升MySQL千万级大表Count(*)查询效率?借助Redis或元数据表实现实时统计?

由于InnoDB引擎下默认使用COUNT(*)走全表扫描(即使有主键),不进行二级索引优化,也无法利用查询缓存(MySQL 8.0已移除),当表行数超过1000万、QPS较高时,单次COUNT(*)操作可能耗时2-5秒,甚至更容易阻塞其他DML操作。

用 Redis 做实时计数的实操要点

适合写多读少、允许短暂误差(秒级)的场景,比如「当前在线用户数」「文章总浏览量」。关键不是存总数,而是控制好增减时机和原子性。

  • INCRBYDECRBY 必须和业务 SQL 在同一事务中触发 —— 但 Redis 本身不参与 MySQL 事务,所以实际要靠应用层双写 + 补偿:先更新 MySQL,再 INCRBY;失败则记录日志,由后台任务重试
  • 不要用 GET + SET 模拟原子增减,会丢数据;必须用 INCRBY
  • 为防 Redis 宕机导致计数丢失,建议每天凌晨用 SELECT COUNT(*) FROM t 全量校准一次,写入 SET t:count:backup 作为兜底值
  • 如果业务有「软删除」,记得在删除逻辑里同步 DECRBY 1;硬删除则通常已含该逻辑

用元数据表替代 COUNT(*) 的落地方式

比 Redis 更可靠,适合要求强一致的场景,比如「会员总人数」「待审核订单数」。本质是把聚合结果物化成一行一列的普通表。

阅读全文
标签:MysqlRedisred