MySQL count()函数

  • MySQL count()函数用来统计结果集中不为null的数据个数
  • 首先存储引擎查询出结果集
  • server层逐个结果判断是否为null,不为null则加1

    count(非索引字段)

  • count(非索引字段)时,server层需要判断每个数据是否为null

  • 而且查询本身无法使用覆盖索引,理论上最慢

select count(first_name) from sakila.customer

count(索引字段)

  • count(索引字段),可以覆盖,依然需要每次判断字段是否为null ```sql

mysql> mysql> show index from customer; +—————+——————+—————————-+———————+——————-+—————-+——————-+—————+————+———+——————+————-+———————-+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +—————+——————+—————————-+———————+——————-+—————-+——————-+—————+————+———+——————+————-+———————-+ | customer | 0 | PRIMARY | 1 | customer_id | A | 599 | NULL | NULL | | BTREE | | | | customer | 1 | idx_fk_store_id | 1 | store_id | A | 2 | NULL | NULL | | BTREE | | | | customer | 1 | idx_fk_address_id | 1 | address_id | A | 599 | NULL | NULL | | BTREE | | | | customer | 1 | idx_last_name | 1 | last_name | A | 599 | NULL | NULL | | BTREE | | | +—————+——————+—————————-+———————+——————-+—————-+——————-+—————+————+———+——————+————-+———————-+ 4 rows in set (0.00 sec)

mysql> explain select count(last_name) from customer; +——+——————-+—————+——————+———-+———————-+———————-+————-+———+———+—————+——————-+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +——+——————-+—————+——————+———-+———————-+———————-+————-+———+———+—————+——————-+ | 1 | SIMPLE | customer | NULL | index | NULL | idx_last_name | 182 | NULL | 599 | 100.00 | Using index | +——+——————-+—————+——————+———-+———————-+———————-+————-+———+———+—————+——————-+ 1 row in set, 1 warning (0.00 sec)

  1. - count(主键),同理,还是需要server层判断是否为null
  2. ```sql
  3. select count(customer_id) from sakila.customer;

count(1)

mysql> select count(1) from customer;
+----------+
| count(1) |
+----------+
|      599 |
+----------+
1 row in set (0.00 sec)

mysql> explain select count(1) from customer;
+----+-------------+----------+------------+-------+---------------+-----------------+---------+------+------+----------+-------------+
| id | select_type | table    | partitions | type  | possible_keys | key             | key_len | ref  | rows | filtered | Extra       |
+----+-------------+----------+------------+-------+---------------+-----------------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | customer | NULL       | index | NULL          | idx_fk_store_id | 1       | NULL |  599 |   100.00 | Using index |
+----+-------------+----------+------------+-------+---------------+-----------------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
  • count(1)只有扫描索引树,没有解析数据行的过程,理论更快。
  • 但是server层依然每次需要判断“1是否为null”

select count(1) from sakila.customer

count(*)

  • count(*)一般用来返回数据表行数
  • MyISAM的count(*)直接返回数据库中记录的数据表行数
  • 由于InnoDB支持事务,数据库中不记录数据表行数
  • MySQL专门优化了count(*)函数直接返回索引树中数据的个数

    总结

  • count(非索引字段):无法使用覆盖索引,最慢

  • count(索引字段):可以使用覆盖索引但依然要取出数据判空
  • count(1):不需要取出数据,但需要判断“1是否为null”
  • count(*):经过专门优化,不需要判空,理论最快