高性能使用索引② 聚簇索引与覆盖索引

260 阅读3分钟

这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

高性能使用索引②

聚簇索引

Innodb和MyIsam的数据分布

MyIsam数据分布:

MyIsam按照数据插入的顺序存储在磁盘上

MyIsam中主键索引和其他索引没有区别,主键索引就是一个名为primary的唯一非空索引。

MyIsam在行的旁边显示了行号,从0递增,可以从表的开头跳过所需字节找到需要的行。

Innodb的数据分布:

聚簇索引的每个叶子节点都包含了主键值、事务ID、用于事务和MVCC的回滚指针和所有剩余列。如果主键是一个列前缀索引,Innodb会包含主键列和剩下的其他列

聚簇索引保存了整个表,和MyIsam使用独立的行存储不同。

Innodb 的二级索引的叶子节点中存储的是主键值

最好避免随机的聚簇索引,特别是对应IO密集型的应用,如果使用UUID作为聚簇索引使得聚簇索引的插入变得完全随机,Innodb可能在插入之前先找到从磁盘读取目标页到内存中,导致大量的随机IO。写入乱序,Innodb不得不频繁做页分裂操作,以便为新的行分配空间。页分裂导致移动大量数据,一次插入最少需要修改三个页,由于频繁页分裂,页变得稀疏并被不规则填充,最终数据会有碎片。

所以使用Innodb尽可能按主键顺序插入数据,尽可能使用单调增加的聚簇键的值插入新行

覆盖索引

一个索引包含所有需要查询的字段的值,我们称为覆盖索引。如果Mysql可以使用索引来直接获取列的数据,就不再需要读取数据行。

覆盖索引必须存储索引列的值,因此Mysql只能使用B-Tree索引做覆盖索引。 而哈希索引、空间索引和全文索引等都不存储索引列的值。

覆盖索引优点:

  • 索引条目远小于数据行大小,所以如果只需要读取索引,mysql就会极大地减少数据访问量。覆盖索引对于IO密集型应用很好,因为索引比数据更小,更容易全部放入内存中
  • 索引按照列值顺序存储,所以对于io密集型的范围查询会比随机从磁盘读取每行数据的io要少得多。
  • MyIsam在内存中只缓存索引,数据依赖操作系统缓存,如果没有覆盖索引,访问数据就需要进行系统调用
  • Innodb的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,就避免了对主键索引的二次查询

这就是聚簇索引和覆盖索引的大体情况了,