mysql InnoDB 索引

索引是什么?
索引类似于书本的目录,目录记录着页码,方便我们的快速查找对应内容;
InnoDB 使用了 B+ 树索引模型,所以数据都是存储在 B+树中的;
一个索引既是一棵B+树。
主键索引和普通索引的区别(InnoDB )
主键索引的叶子节点存的是整行数据,主键索引也被称为聚簇索引;
非主键索引的叶子节点内容是主键的值,非主键索引也被称为二级索引;

如果语句是 select * from T where ID=500 即主键查询方式,则只需要搜索 ID 这棵B+ 树;
如果语句是 select * from T where k=5 即普通索引查询方式,则需要先搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表。
也就是说,基于非主键索引的查询需要多扫描一棵索引树。我们在应用中应该尽量使用主键查询。

索引维护
B+ 树为了维护索引有序性,在插入新值的时候需要做必要的维护。
如果新插入值在现有数据的末尾,则可以直接追加;
如果新插入值不是在现有数据的,则插入数据之后的数据需要做逻辑后移;

而更糟的情况是,如果插入数据所在的数据页已经满了,根据 B+ 树的算法,这时候需要申请一个新的数据页,然后挪动部分数据过去。这个过程称为页分裂。在这种情况下,性能自然会受影响。
补充:数据页(Page)是 Innodb 存储引擎用于管理数据的最小磁盘单位

除了性能外,页分裂操作还影响数据页的利用率。原本放在一个页的数据,现在分到两个页中,整体空间利用率降低大约 50%。

当然有分裂就有合并。当相邻两个页由于删除了数据,利用率很低之后,会将数据页做合并。合并的过程,可以认为是分裂过程的逆过程。

由于每个非主键索引的叶子节点上都是主键的值。如果用身份证号做主键,那么每个二级索引的叶子节点占用约 20 个字节,而如果用整型做主键,则只要 4 个字节,如果是长整型(bigint)则是 8 个字节

主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。

覆盖索引
如果执行的语句是 select ID from T where k between 3 and 5,这时只需要查 ID 的值,而 ID 的值已经在 k 索引树上了,因此可以直接提供查询结果,不需要回表。也就是说,在这个查询里面,索引 k 已经“覆盖了”我们的查询需求,我们称为覆盖索引。由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。

需要注意的是,在引擎内部使用覆盖索引在索引 k 上其实读了三个记录,R3~R5(对应的索引 k 上的记录项),但是对于 MySQL 的 Server 层来说,它就是找引擎拿到了两条记录,因此 MySQL 认为扫描行数是2。

需要查询的值都在一个索引上即是覆盖索引
验证是否使用上了覆盖索引
explain select ID from T where k between 3 and 5
列 extra 显示 using index 则代表 覆盖索引;
最左前缀原则
当已经有了 (a,b)这个联合索引后,一般就不需要单独在 a 上建立索引了。因此,第一原则是,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。

如果既有联合查询,又有基于 a、b 各自的查询呢?查询条件里面只有 b 的语句,是无法使用 (a,b) 这个联合索引的,这时候你不得不维护另外一个索引,也就是说你需要同时维护 (a,b)、(b) 这两个索引。

posted @ 2021-12-09 14:30  deja_ve  阅读(77)  评论(0)    收藏  举报