MySQL的聚簇索引和覆盖索引

2020-10-24  本文已影响0人  雁阵惊寒_zhn

聚簇索引

聚簇索引不是一种单独的索引类型,而是一种数据存储方式。InnoDB聚簇索引的数据行实际上存放在索引的叶子页(leaf page)中。“聚簇”代表着数据行和相邻的键值紧凑地存储在一起,InnoDB通过主键聚集数据,如果不存在主键,InnoDB会选择唯一的非空索引,如果也没有唯一非空索引,InnoDB隐式定义一个主键来作为聚簇索引。一张表中只能存在一个聚簇索引。

聚簇索引优点

  1. 可以把相关数据保存在一起。
  2. 数据访问速度更快。索引和数据保存在同一棵B+Tree中,因此从聚簇索引获取数据更快些。
  3. 使用覆盖索引扫描的查询可以直接使用叶节点中的主键值。
  4. 聚簇索引最大限度提升了IO密集型应用的性能。

聚簇索引缺点

  1. 插入速度严重依赖插入顺序。
  2. 更新聚簇索引代价高。
  3. 聚簇索引可能引起页分裂(page split),页分裂会导致表占用更多的磁盘空间。
  4. 聚簇索引可能导致全表扫描变慢,尤其是行稀疏,或者页分裂导致数据存储不连续的时候。
  5. 二级索引(非聚簇索引)可能比想象的要更大,因为在二级索引的叶子节点包含了引用行的主键列。
  6. 二级索引访问需要两次索引查找,而不是一次。二级索引叶子节点保存的不是指向行的物理位置的指针,而是行的主键值。

InnoDB聚簇索引的存储

InnoDB中聚簇索引“就是”表。聚簇索引的每一个叶子节点都包含了主键值、事务ID、用于事务和MVCC的回滚指针以及所有剩余的列。InnoDB二级索引的叶子节点中存储的不是行指针,而是主键值。这样的设计减少了行移动或者页分裂时二级索引的维护成本,但是在二级索引访问时却需要两次索引查找。
InnoDB聚簇索引尽可能地按主键顺序插入数据,并且尽可能地使用单调增加的聚簇键的值来插入新行。
InnoDB聚簇索引的存储如下图所示:


截图自《高性能MySQL(第三版)》

覆盖索引

如果一个索引包含(覆盖)所有需要查询的字段值,我们就称之为“覆盖索引”。

下面的情况适合使用覆盖索引,查询时只扫描覆盖索引,而不需回表查询。

  1. 索引条目通常远小于数据行大小,只读取索引,会减少访问量。
  2. 索引按照列值顺序存储,对于范围查询效率更高。
  3. InnoDB二级索引如果能够覆盖索引,可以避免对主键索引的二次查询。
  4. 若索引缓存在内存中,查询时开销更小。

关于索引可能的面试题

问题一:MySQL的底层数据结构

MyISAM引擎索引文件和数据文件是分离的,InnoDB引擎索引数据文件本身就是索引文件(聚簇索引)。

问题二:为什么InnoDB表必须有主键,并且推荐使用整型的自增主键

InnoDB通过主键聚集数据,如果不存在主键,InnoDB会选择唯一的非空索引,如果也没有唯一非空索引,InnoDB隐式定义一个主键来作为聚簇索引。
自增主键可以保证数据顺序增加,如果不是顺序增加,会引起B+Tree叶子节点因为插入导致的数据检索,页分裂和保持顺序等消耗,而顺序增加只需要在B+Tree最后叶子节点加入就可以了。

问题三:为什么非主键索引结构叶子节点存储的是主键值

这样的设计减少了行移动或者页分裂时二级索引的维护成本,但是在二级索引访问时却需要两次索引查找。

上一篇下一篇

猜你喜欢

热点阅读