我们先准备好测试数据
create table user_test_count
(
id int primary key not null auto_increment,
name varchar(45),
age int,
email varchar(60),
birthday date
) engine 'innodb';
insert into user_test_count (id, name, age, email, birthday)
values (1, '张三', 20, 'zhangsan@aaa.com', '2000-01-01');
insert into user_test_count (id, name, age, email, birthday)
values (2, '李四', 30, 'lisi@bbb.com', '1990-01-01');
insert into user_test_count (id, name, age, email, birthday)
values (3, '王五', 40, null, null);
insert into user_test_count (id, name, age, email, birthday)
values (4, '赵六', 50, null, null);
我们先直接使用count(*)
explain select count(*) from user_test_count;
可以看到key使用了主键
然后我们给email
字段添加一个索引
我们再次执行上述explain语句,可以看到这次使用了email的索引,key_len长度为243
然后我们再添加一个birthday
字段的索引
执行上述explain语句,这次使用了birthday的索引,key_len长度为4
由此我们可以得出以下结论:
- 当没有非主键索引时,会使用主键索引
- 如果存在非主键索引的话,会使用非主键索引
- 如果存在多个非主键索引,会使用一个最小的非主键索引
其原因是:在innodb中,非主键索引叶子节点存储的结构是:索引+主键;主键索引叶子节点是:主键+表数据。在1个page里面,非主键索引可以存储更多的条目,例如:
对于一张表,如果有1000000数据,使用非主键索引扫描的page数可能是100 ,而使用主键索引page数可能是500,此时使用非主键索引的性能会更好。同理如果存在多个非主键索引,会使用一个最小的非主键索引,也是为了在一个page里存储更多的数据,从而减少扫描次数,提高性能。
我们可以再试一下单字段的count
explain select count(email) from user_test_count;
可以看到还是撞在email
的索引上
说明:count(字段)只会针对该字段统计,使用这个字段上面的索引