最近的工作中,遇到一个查询里用到主键索引与二级索引并存的问题情况,那对于这种情况,索引是如何高效执行的,是否会产生回表查询呢?
1、两类索引
1.1 聚集索引(聚簇索引)
如果表定义了PK(Primary Key,主键),那么PK就是聚集索引。 如果表没有定义PK,则第一个NOT NULL UNIQUE的列就是聚集索引。 否则InnoDB会另外创建一个隐藏的ROWID作为聚集索引。
1.2 非聚集索引(普通索引、非聚簇索引、二级索引)
2、应用示例
一例胜千言,show me you code!
2.1 建表操作
mysql> create table user( -> id int(10) auto_increment, -> name varchar(30), -> sex tinyint(4), -> type varchar(8), -> primary key (id), -> index idx_name (name) -> )engine=innodb charset=utf8mb4;
id 字段是聚簇索引,name 字段是普通索引(二级索引)
2.2 填充数据
mysql> select * from user;+----+--------+------+------+| id | name | sex | type |+----+--------+------+------+| 1 | sj | m | A || 3 | zs | m | A || 5 | ls | m | A || 9 | ww | f | B |+----+-----+-----+-----+
2.3 索引结构
聚簇索引(ClusteredIndex)
id 是主键,所以是聚簇索引,其叶子节点存储的是对应行记录的数据
普通索引(secondaryIndex)
name 是普通索引(二级索引),非聚簇索引,其叶子节点存储的是聚簇索引的的值
2.4 查找过程
普通索引查找过程
如果查询条件为主键(聚簇索引),则只需扫描一次B+树即可通过聚簇索引定位到要查找的行记录数据。
select * from user where name = 'lisi';
普通索引因为无法直接定位行记录,其查询过程在通常情况下是需要扫描两遍索引树的。
3、索引覆盖
3.1 如何实现覆盖索引
explain select id, name from user where name = 'lisi';
explain分析:因为name是普通索引,使用到了name索引,通过一次扫描B+树即可查询到相应的结果,这样就实现了覆盖索引