在mysql优化中,是count主键快还是count二级索引快?Mysql 版本5.7.26
我来测试一下:
1.建一张只有主键的表
CREATE TABLE sbtest1 (
id int(11) NOT NULL AUTO_INCREMENT,
k int(11) NOT NULL DEFAULT ‘0’,
c char(120) NOT NULL DEFAULT ‘’,
pad char(60) NOT NULL DEFAULT ‘’,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1DEFAULT CHARSET=latin1
2.加载数据查看表空间占用情况,大概1.4G
[root@localhost sbtest]# ll -h sbtest1*
-rw-r----- 1 root root 8.5K Jun 7 10:35 sbtest1.frm
-rw-r----- 1 root root 1.4G Jun 7 10:40 sbtest1.ibd
3.防止缓存,重启mysql, count主键耗时11秒左右。
[root@localhost node1]# ./restart
stop /root/sandboxes/all_masters_msb_5_7_26/node1
. sandbox server started
node1 [localhost:21227] {root} ((none)) > select count(id) from sbtest.sbtest1;
±----------+
| count(id) |
±----------+
| 6400000 |
±----------+
1 row in set (11.94 sec)
node1 [localhost:21227] {root} ((none)) > select * from sys.innodb_buffer_stats_by_table where object_name=‘sbtest1’;
±--------------±------------±----------±---------±------±-------------±----------±------------+
| object_schema | object_name | allocated | data | pages | pages_hashed | pages_old | rows_cached |
±--------------±------------±----------±---------±------±-------------±----------±------------+
| sbtest | sbtest1 | 1.34 GiB | 1.23 GiB | 87675 | 0 | 32314 | 6401167 |
±--------------±------------±----------±---------±------±-------------±----------±------------+
4.建二级索引,
node1 [localhost:21227] {root} ((none)) > create index idx_k on sbtest.sbtest1(k);
Query OK, 0 rows affected (7.81 sec)
Records: 0 Duplicates: 0 Warnings: 0
5.重启mysql,count二级索引耗时1秒左右
[root@localhost node1]# ./restart
stop /root/sandboxes/all_masters_msb_5_7_26/node1
node1 [localhost:21227] {root} ((none)) > select * from sys.innodb_buffer_stats_by_table where object_name=‘sbtest1’;
Empty set (0.27 sec)
node1 [localhost:21227] {root} ((none)) > select count(k) from sbtest.sbtest1;
±---------+
| count(k) |
±---------+
| 6400000 |
±---------+
1 row in set (0.86 sec)
node1 [localhost:21227] {root} ((none)) > select * from sys.innodb_buffer_stats_by_table where object_name=‘sbtest1’;
±--------------±------------±-----------±-----------±------±-------------±----------±------------+
| object_schema | object_name | allocated | data | pages | pages_hashed | pages_old | rows_cached |
±--------------±------------±-----------±-----------±------±-------------±----------±------------+
| sbtest | sbtest1 | 338.78 MiB | 313.92 MiB | 21682 | 0 | 8241 | 3799997 |
±--------------±------------±-----------±-----------±------±-------------±----------±------------+
1 row in set (0.42 sec)
为什么count二级索引比count主键要快呢?
Mysql表的主键是cluster index, cluster indexd存数据是紧密排布,Mysqlr 二级索引是只存键值和主键值。
以表数所据为例,看一下他们存数据的区别:
id name age
1 hjp 10
2 abc 15
3 cls 20
4 ddd 30
5 eee 40
6 fff 50
Cluster index 存的数据如下图

mysql二级索引存的是键值和主键值。假如name为二级索引,数据如下图:

从以上的测试可以看出,count 主键时,基本把表的数据全描了,sys.innodb_buffer_stats_by_table表的allocated字段为1.34G,和ibd文件差不多大,基本全描到缓存了。而二级索引,allocated字段为338.78 MiB,基本就是索引的大小。
总结一下:
1.mysql的二级索引count比主键快,这和索引的存储结构有关。
2.对于用主键作为询条件的SQL,用主键查询比二级索引快,主键查询少一次回表IO。




