为什么SQL查询中用COUNT(DISTINCT)去重计数性能那么糟糕?

2026-04-29 01:150阅读0评论SEO教程
  • 内容介绍
  • 相关推荐

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

为什么SQL查询中用COUNT(DISTINCT)去重计数性能那么糟糕?

基本原因在于执行路径的不同:

子查询写法必须满足的三个前提条件

不是所有 SELECT COUNT(*) FROM (SELECT DISTINCT ...) 都快,它只在以下情况真正生效:

  • WHERE 条件足够强,能大幅减少输入行数(比如 dt >= '2026-04-15',而不是 status IN ('a','b','c') 这种低选择率条件)
  • 去重字段 col 有单列索引或作为联合索引最左前缀(否则子查询仍要全表扫)
  • 子查询结果集行数远小于原始表(理想是 COUNT(*) 反而多一次遍历

MySQL中容易被忽略的索引陷阱

即使你给 user_id 加了索引,COUNT(DISTINCT user_id) 仍可能不走索引——因为 MySQL 优化器发现去重逻辑无法跳过 NULL 值判断或需要回表取其他字段时,会主动放弃索引扫描。

阅读全文

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

为什么SQL查询中用COUNT(DISTINCT)去重计数性能那么糟糕?

基本原因在于执行路径的不同:

子查询写法必须满足的三个前提条件

不是所有 SELECT COUNT(*) FROM (SELECT DISTINCT ...) 都快,它只在以下情况真正生效:

  • WHERE 条件足够强,能大幅减少输入行数(比如 dt >= '2026-04-15',而不是 status IN ('a','b','c') 这种低选择率条件)
  • 去重字段 col 有单列索引或作为联合索引最左前缀(否则子查询仍要全表扫)
  • 子查询结果集行数远小于原始表(理想是 COUNT(*) 反而多一次遍历

MySQL中容易被忽略的索引陷阱

即使你给 user_id 加了索引,COUNT(DISTINCT user_id) 仍可能不走索引——因为 MySQL 优化器发现去重逻辑无法跳过 NULL 值判断或需要回表取其他字段时,会主动放弃索引扫描。

阅读全文