资讯详情

InnoDB 的B+树索引原理

每个表至少有一个主键索引,表中所有的数据线都存储在主键索引中 B 树的叶子节点上的。如果你给表的其他字段加了索引的话,这个索引就是二级索引了,二级索引也是 B 树。

二级索引和主键索引的区别在于叶节点上保存的值不同。表中所有字段的值都完全保存在主键索引的叶节点上,但二级索引的叶节点只保存相应的主键值。表上有多少索引,实际上有多少索引 B 树。

让我们举一个具体的例子来恢复这个问题。首先提供一个表,表中有三个字段 (id,k,m),分别给主键 id 和字段 k 建立主键索引和二级索引。

mysql> create table t( id int primary key,  k int not null,  m int(11), index (k)) engine=InnoDB; 

然后在表中插入几个数据R1、R2、R3、R4、R插入的具体数据如下:R1~R5 的 (id,k,m) 值分别为 (100、1、1000)、(200、2、2000)、(300、3、3000)、(500、5、5000)、(600、6、6000)。

整行记录值保存在主键索引叶节点上,主键值保存在二级索引叶节点上,因此上表 t 的数据在 mysql 底层的存储如下示意图所示。

img

表 t 一共有 3 字段,字段 m 上面没有索引,也就是说表格 t 上面有两个索引,所以对应有 2 个 B 树,表上有多少索引,实际上会有多少索引 B 树。

接下来我们来看看索引和没有索引的查询区别。

比如下面这个 sql 句子,显然没有可用的索引,所以你只能扫描整个表,也就是说,从头到尾扫描主键索引上的叶节点,然后扫描每行字段 m 拿出值进行比较,筛选出符合条件的记录,这个查询效率很低。

 select * from t where m > 1000 and m < 3000; 

再来看看另一个 sql 这个句子可以使用索引 k,所以这个查询会先到二级索引 k 这个 B 在树上,快速找到满足要求的叶节点,这里的叶节点只保存了主键值,因此需要获得主键 ID 值回到主键索引上找出所有字段的值,称为

select * from t where k > 3 and k < 6; 

回表过程也可以重新优化,即使用

二、覆盖索引

假如只有一次 B 树可以得到我们想要的数据,也就是说,没有返回过程,这个效率显然很好,这就是覆盖索引的优点。下面是一个具体的例子。

mysql> create table user( id int(11) primary key,  name varchar(20) not null,  age int(11), sex int(11), index (age)) engine=InnoDB;

依然是新建一个表,创建索引,插入一些测试数据,注意这里只是为了解释说明覆盖索引,并不表示 mysql 的真实执行方式,因为会涉及到 mysql 的优化器机制,这里暂且不说了。

1    bob 16  1
2    kom 19  0
3    gum 18  1
4    tt  20  1
5    yy  25  1

创建一个 user 表,给 age 字段添加一个二级索引,并插入上面五条数据,然后看下面这条查询语句。

select name from user where age between 18 and 21

1、age 字段上有索引,mysql 会先到 age 字段的 B+ 树上找到满足条件的第一个叶子节点(age=19),这个叶子节点上保存了对应主键 id 的值 2,然后再到主键索引上找到 id 为 2 的这条记录,同时把 name 字段拿出来。

2、重复第一步的操作,继续从 age 索引上的叶子节点往后遍历找出满足条件的第二个叶子节点,同样回到主键上拿出 name 字段的值,直到遍历到不满足条件的叶子节点(age=25)。

也就是说,这条 sql 语句虽然用到了索引,但是 age 索引上并没有要查询的 name 字段,所以只能回表到主键索引上查出 name 字段,所以这个过程其实是遍历了个两个 B+ 树。

那么我们删除 age 这个单列索引,创建一个覆盖索引 (age,name), 把要查询的 name 字段也添加到索引中来。

#删除原索引
drop INDEX age on USER
#新建覆盖索引
ALTER TABLE USER add index age_name(age,name)

由于现在这个覆盖索引上的字段包含了要查询的 age 和 name 字段,免去了到主键索引上查询数据的过程,其实也就是只遍历了一个 B+ 树,可以大大提升查询效率。

总之,在设计索引或者优化 sql 语句的时候,要尽量避免回表操作,所以使用覆盖索引是一种常用的 sql 优化手段。

所以我们平时写 sql 语句的时候,select 后面只写查询需要用到的字段,去掉不需要的字段,避免回表操作。

标签: 1kom电位器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台