1. COUNT 函数的作用 数据库系统中COUNT(expr)用于统计数据行数,其主要作用为返回SELECT语句检索的行中 expr 表达式的值不为 NULL 的行的数量,返回值是一个 BIGINT 值,如果查询结果没有命中任何记
1. COUNT 函数的作用数据库系统中 COUNT(expr)用于统计数据行数,其主要作用为返回SELECT语句检索的行中 expr 表达式的值不为 NULL 的行的数量,返回值是一个 BIGINT 值,如果查询结果没有命中任何记录则返回 0。 通常的使用方式主要有以下两种:
2. COUNT(*) 与 COUNT(1) 与 COUNT(column)COUNT(expr)统计的是 expr 不为 NULL的行数,而在COUNT(column)、 COUNT(1)和 COUNT(*)三种用法中,expr 分别是列名、 常量和*。 这三个条件中常量是一个固定值,肯定不为NULL。 *可以理解为查询整行,所以肯定也不为NULL,只有列名的查询结果有可能是NULL。 故 COUNT(1) 和 COUNT(*) 可认为是直接查询符合条件的数据库表的行数,而COUNT(column)表示的是查询符合条件的列的值不为NULL的行数。
相比 COUNT(*),COUNT(column) 多了一个判断所查询的字段是否为 NULL 的步骤,所以效率要比 COUNT(*) 低 3. MySQL 对 COUNT 的优化这些优化的前提都是查询语句中不包含 WHERE 及 GROUP BY 限定条件 3.1 MyISAM 引擎优化MyISAM 引擎的锁是表级锁,同一张表上的操作都是串行完成,故MyISAM做了一个简单的优化,就是把表的总行数单独记录下来。 使用 COUNT(*) 查询表的总行数时,直接返回这个记录下来的数值就可以了,当然前提是不能有where条件 MyISAM之所以可以把表的总行数记录下来供COUNT(*)查询使用,是因为MyISAM数据库是表级锁,不会有并发的数据库行数修改,所以查询得到的行数是准确的 3.2 InnoDB 引擎优化因为 InnoDB 支持事务,其中大部分操作都是行级锁,所以表的行数可能会被并发修改,在这种情况下将总行数记录下来的方式就不准确了。 因此 InnoDB 中使用 COUNT( * ) 查询行数的时候,不可避免地要进行扫表,只能在扫表过程中来优化效率 我们知道,InnoDB 中索引分为聚簇索引(主键索引)和非聚簇索引(非主键索引),聚簇索引的叶子节点中保存的是整行记录,而非聚簇索引的叶子节点中保存的是该行记录的主键的值。 COUNT(*)只是为了统计总行数,不用关心查到的具体值,如果在扫表的过程中选择一个成本较低的索引的话,那就可以大大节省时间。 显而易见,非聚簇索引要比聚簇索引小很多,所以 InnoDB 引擎会优先选择最小的非聚簇索引来扫表。 根据这个特性可知,建表的时候除了主键索引以外,创建一个非主键索引也很有必要 4. COUNT 查询优化假设有一张表t_user,里面有大概5000条记录,一个需求是统计 id 大于 20 的用户数量,以下两种写法效率大不相同 简单的条件查找,近乎扫描全表,表较小时效率很高,表数据较多就很耗时
另一个思路是先统计 id 小于 20 的记录,再使用总的行数减去该值就得到了结果。 这是因为查询优化阶段会把该类子查询当作常数处理,只需扫描 id < 20 的行,开销大幅减少
|
2021-06-02
2021-06-05
2022-06-27
2024-02-19
2022-10-12