【问题标题】:What to count when counting all rows MySQL计算所有行MySQL时要计算什么
【发布时间】:2015-10-21 10:21:58
【问题描述】:

在计算 * 、任何自定义字段 ( n ) 或 MySQL 中的 primary id 时,性能或后台执行行为是否有任何差异?

* 在查询中具体指的是什么,它与其他两种方式有何不同?

SELECT COUNT( * ) FROM t;
SELECT COUNT( id ) FROM t;
SELECT COUNT( n ) FROM t;

更新:

假设idn 在任何记录中都不为空。

【问题讨论】:

  • Count(*) 计算所有,count(id) 只计算非空值
  • 您无法真正比​​较返回不同结果的查询的性能:-?
  • 让我们假设,主 id 在任何记录中都不为空。我想,这很正常。
  • 正确。这个问题实际上与性能无关,因为提供的选项提出了两个不同的问题。如果一个表有一个 PK,那么几乎可以肯定 count(*) 将通过计算索引中的行数来实现。
  • 统计所有行,也可以使用count(1)

标签: mysql sql performance select count


【解决方案1】:
COUNT(*) will include NULLS
COUNT(column_or_expression) won't.

这意味着COUNT(any_non_null_column) 将给出与COUNT(*) 相同的值,因为没有 NULL 值会导致差异。

一般来说,COUNT(*) 应该更好,因为可以使用任何索引,因为 COUNT(column_or_expression) 可能无法被索引或 SARGable

来自ANSI-92(查找“标量表达式 125”)

案例:

a) 如果指定了COUNT(*),则结果是T的基数。

b) 否则,令 TX 为应用 到 T 的每一行并消除空值。 如果消除了一个或多个空值,则完成条件为 引发:警告 - 在 set 函数中消除空值。

同样的规则至少也适用于 SQL Server 和 Sybase

注意:COUNT(1)COUNT(*) 相同,因为 1 是一个不可为空的表达式。

【讨论】:

    【解决方案2】:

    count(*) 在某些情况下有一些优化(查询没有where 子句的单个 MyISAM 表),这可能是 OP 中的情况,具体取决于存储引擎。如果您的查询没有遇到这种特殊情况,MySQL 将必须构建一个执行计划并正常运行查询,如果您有主键,这将与 count(my_primary_key) 一样好(或坏)。

    长话短说 - 不要想太多。只需使用count(*) 并让数据库担心优化您的查询。毕竟,它就是为此而构建的。

    【讨论】:

    • count(*) 和 count(primary key) 不一样
    • @Mihai - 为什么它们不同?
    • @RickJames 一个算空,另一个不算。
    • @Mihai 主键没有考虑 - 也不计算空值。
    【解决方案3】:

    对于 InnoDB 表,您可能会发现“最小”索引用于 COUNT(*)COUNT(1)COUNT(id)。要看到这个,请EXPLAIN SELECT COUNT(...) FROM tbl;

    如果您没有二级索引,则必须扫描“表”。

    请注意,每个辅助键都包含PRIMARY KEY 的列。所以,对于

    PRIMARY KEY(a, b)
    INDEX c_d (c, d)
    

    可能对这 4 列中的任何一个或 (1)(*) 的任何计数都将使用 c_d 索引。

    COUNT(e) 需要扫描表。

    【讨论】:

      猜你喜欢
      • 2011-09-02
      • 1970-01-01
      • 1970-01-01
      • 2014-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多