【问题标题】:mysql COUNT(*) vs COUNT(DISTINCT col)mysql COUNT(*) 与 COUNT(DISTINCT col)
【发布时间】:2016-04-04 15:26:15
【问题描述】:

Q1:为什么 count(*) 比 count(distinct col) 慢很多?

Q2:id 应该总是使用 count(distinct col) 吗?

select count(id) from source;
+-----------+
| count(id) |
+-----------+
|     22713 |
+-----------+
1 row in set (0.73 sec)

mysql> select count(distinct id) from source;
+--------------------+
| count(distinct id) |
+--------------------+
|              22836 |
+--------------------+
1 row in set (0.08 sec)

【问题讨论】:

  • 你的架构是什么样的?您是否使用 explain 运行查询?
  • 要确定我们需要查看表结构、索引和解释计划。 Count distinct id 准确返回字段的不同计数。 count(id) 将返回重复项的计数(如果存在)。您的结果的奇怪之处在于,如果没有发生数据更改,则不同计数大于我永远不会期望的计数。如果 ID 已编入索引,引擎会简单地计算 idx 中的唯一值,如果它已编入索引并且有重复项,则可能必须执行全表扫描。不,你不应该总是使用一个,在你的结果中使用你需要的东西
  • 在我看来,您的结果与使用的 SQL 配对不正确。如果它们正确配对,我无法理解为什么 count(ID) 在同一个数据源上会 > count (Distinct ID)。 (除非表统计信息或索引损坏)

标签: mysql


【解决方案1】:

如果列被索引,COUNT(DISTINCT id) 只需要返回列的索引中的项目数。 COUNT(id) 必须将每个索引条目指向的行数相加,或者扫描所有行。

关于您的第二个问题,请参阅count(*) and count(column_name), what's the diff?。大多数时候,COUNT(*) 是最合适的;在某些情况下,例如计算与外连接连接的行,您需要使用COUNT(columnname),因为您不想计算空行。

【讨论】:

    【解决方案2】:

    如果查询被mysql缓存也可能会更快

    这是我的测试,大约有 150 万行,id 是 auto_increment PK

    【讨论】:

      【解决方案3】:

      1) 确保查询结果没有被缓存

      2) 似乎 ID 列具有 NULL 参数和索引。在这种情况下,count(id) 为具有 NOT NULL 值的 id 提供计数。如果列 ID 没有 NULL 参数 - 使用 COUNT(*)。它为您提供行数,而无需检查每一行的“列!== null”

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-16
        • 1970-01-01
        • 2013-05-12
        • 2015-01-28
        • 1970-01-01
        • 1970-01-01
        • 2012-10-13
        • 2010-09-19
        相关资源
        最近更新 更多