3、赫敏 格兰杰 --- 浅谈索引

低年级时期的赫敏 真的好漂亮

InnoDB中的索引模型

在InnoDB中表都是跟随主键顺序,以索引的形式存放的。这种存储方式的表称为索引组织表。
InnoDB采用了B+tree索引模型,所以数据都是存储在B+中的

每一个索引在InnoDB中对应一颗 B+

主键索引的子叶节点存的是整行数据。在InnoDB里,主键索引也叫聚簇索引

非主键索引的子叶节点内容是主键的值。在InnoDB里,非主键索引也叫二级索引。

基于主键索引和普通索引查询的区别?

mysql> create table T(
id int primary key, 
k int not null, 
name varchar(16),
index (k))engine=InnoDB;

select * from T where id=500; 对于主键查询方式,只需要搜索ID这颗B+
select * from T where k=5; 普通索引查询方式,首先搜索k索引,获得对应的ID值,在用Id在 id索引在搜索一次,这个过程叫做回表。
so,赫敏温馨提醒 :尽量使用主键索引咯~~~

索引的维护

image.png

B+为了维护索引的有序性,在插入新值的时候就需要做必要的维护,以上面这个图为例,如果插入新的行 ID 值为 700,,则只需要在 R5 的记录后面插入一个新记录。如果新插入的 ID 值为 400,就相对麻烦了需要逻辑上挪动后面的数据,空出位置。

而更糟的情况是,如果 R5 所在的数据页已经满了,根据 B+ 树的算法,这时候需要申请一个新的数据页,然后挪动部分数据过去。这个过程称为页分裂。在这种情况下,性能自然会受影响。
除了性能外,页分裂操作还影响数据页的利用率。原本放在一个页的数据,现在分到两个页中,整体空间利用率降低大约 50%。
当然有分裂就有合并。当相邻两个页由于删除了数据,利用率很低之后,会将数据页做合并。合并的过程,可以认为是分裂过程的逆过程。



mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0, 
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB;

insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');

如果我执行 select * from T where k between 3 and 5,需要执行几次树的搜索操作,会扫描多少行?

1、在 k 索引树上找到 k=3 的记录,取得 ID = 300...
2、再到 ID 索引树查到 ID=300 对应的 R3;
3、在 k 索引树取下一个值 k=5,取得 ID=500;
4、再回到 ID 索引树查到 ID=500 对应的 R4;
5、在 k 索引树取下一个值 k=6,不满足条件,循环结束。

在这个过程中,回到主键索引树搜索的过程,我们称为回表。可以看到,这个查询过程读了 k索引树的 3 条记录(步骤 1、3 和 5),回表了两次(步骤 2 和 4)。

索引覆盖

如果执行的语句是 select ID from T where k between 3 and 5,这时只需要查 ID 的值,而ID 的值已经在 k 索引树上了,因此可以直接提供查询结果,不需要回表。也就是说,在这个查询里面,索引 k 已经“覆盖了”我们的查询需求,我们称为索引覆盖。

由于索引覆盖可以减少索引树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能提升手段

最左前缀原则

B+ 树这种索引结构,可以利用索引的“最左前缀”,来定位记录。
在建立联合索引的时候,如何安排索引内的字段顺序。
第一原则是,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。
还要考虑到空间原则


联合索引(name, age)


image.png

可以看到。索引项是按照索引定义里面出现的字段顺序排序的。

索引下推

mysql> select * from tuser where name like '张 %' and age=10 and ismale=1;

Mysql5.6 引入索引下推优化(index condition pushdown) ,在索引遍历过程中,
对索引包含的字段先进行判断,直接过滤掉不符合条件的记录,减少回表次数。


image.png

鸣谢 林晓斌 发布在极客时间上的Mysql45讲 格兰杰用金加隆订阅的哦~~~

你可能感兴趣的:(3、赫敏 格兰杰 --- 浅谈索引)