InnoDB 中,表数据文件自身就是以主键为索引的 B + 树,树的叶子节点寄存一条条表数据,此索引树被称为表的聚簇索引。聚簇索引也称为汇集索引,聚类索引,簇集索引,聚簇索引确定表中数据的物理程序。
InnoDB 聚簇索引
InnoDB 表主键
InnoDB 中每张表都会有一个主键,表中的每一行数据都是依照主键的程序在聚簇索引中存储的,InnoDB 中有两种形式确定一行数据的主键:
- 显式申明:用户能够在建表的时候通过
primary key
关键字来申明主键列; - 惟一索引:如果用户没有申明主键列,那么 InnoDB 会应用第一个非空惟一列作为主键;
- 主动生成:如果满足以上两种条件的列都不存在,那么 InnoDB 会将 RowId 作为主键;
聚簇索引示例
首先咱们在数据库中建设一张用户表,蕴含用户 ID、姓名、性别、年龄四个字段:
create table user_info
(
id int primary key,
age int not null,
name varchar(16),
sex bool
)engine=InnoDB;
向数据库中插入如下数据:
用户 ID | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
姓名 | 陈尔 | 张散 | 李思 | 王舞 | 赵流 | 孙期 | 周跋 | 吴酒 | 郑史 |
性别 | 男 | 男 | 女 | 女 | 男 | 男 | 男 | 女 | 男 |
年龄 | 5 | 10 | 20 | 28 | 35 | 56 | 25 | 80 | 90 |
上述表中插入指定数据后,失去的聚簇索引构造如下所示:
能够看到,聚簇索引的叶子节点蕴含了所有数据,所以在须要查问某一行数据的所有列时,通过聚簇索引查问的效率最高。
非聚簇索引
InnoDB 中,除了聚簇索引以外,其余的索引都能够称为非聚簇索引,非聚簇索引的叶子节点寄存主键索引,而不是所有数据。通过非聚簇索引查找数据,其流程是先通过非聚簇索引查找到数据的主键,再通过主键查找对应的数据。
对于上文中的用户表,咱们略微批改一下建表语句,对用户的年龄增加索引:
create table user_info
(
id int primary key,
age int not null,
name varchar(16),
sex bool,
key(age)
)engine=InnoDB;
向表中插入和上文中雷同的数据,InnoDB 会为这张表生成两个索引树:用户 ID 对应的聚簇索引树和用户年龄对应的非聚簇索引树,其构造如下图所示。
从图中能够发现,聚簇索引和非聚簇索引最大的区别就是叶子节点寄存的内容,聚簇索引的叶子节点寄存了数据库一行中的所有数据,而非聚簇索引的叶子节点寄存了数据的主键。
大多数状况下,通过非聚簇索引查找到主键值后,还须要通过主键值去聚簇索引查找整行数据,从而获取到满足条件行的所有数据。所以非聚簇索引的查问速度总是会比聚簇索引的查问速度慢一些,日常开发中能应用聚簇索引应该尽量应用聚簇索引。
回表查问
所谓的回表查问,就是指通过非聚簇索引查问数据时,可能须要回到聚簇索引多查问一次数据的状况,对于上文中的数据,执行以下 SQL 语句,其查问过程如下图中的绿色门路所示。
从图中能够看到,在用户年龄的索引树的叶子节点中,蕴含了用户的主键 ID,因为咱们须要获取用户的所有信息,所以还须要依照用户的 ID 去聚簇索引查找用户的所有信息。
select * from user_info where age = 5;
笼罩索引
如果某次查问的过程中,查问须要的数据在非聚簇索引中就能够失去,那么就没有必要回到聚簇索引查问行所有的数据,这种状况称为笼罩索引。咱们能够把下面回表查问的 SQL 批改为:
select id from user_info where age = 5;
因为年龄索引树的叶子节点就蕴含了 ID 信息,所以 InnoDB 不须要回聚簇索引再次查问用户 ID,而是间接将年龄索引树中的 ID 返回。
本文最先公布至微信公众号,版权所有,禁止转载!