InnoDB引擎--索引

良好的索引设计可以大大提高数据库查询性能。InnoDB引擎支持自适应哈希索引、B+树索引和全文索引。其中自适应哈希索引是系统自动调整的,用户无法干预。

B+树索引

聚集索引

聚集索引以主键顺序构建B+树,叶子节点中存储行数据记录,数据也是索引的一部分。

辅助索引

辅助索引以索引列逻辑顺序构建B+树,叶子节点中不存储实际的行数据记录,而存储的是行数据的聚集索引键

InnoDB聚集索引和辅助索引检索过程图:
这里写图片描述
如图所示,主键索引的叶子节点上存储了实际行数据,而辅助索引叶子节点上存储的是主键。通过主键查询行记录时,只需要使用主键索引;通过辅助索引查询行记录时,如果查询的是辅助索引列数据,则可以直接使用辅助索引,如果需要更多数据,则需要再次访问主键索引。

索引的开销

使用索引需要占用额外的磁盘空间和更新操作中的时间。空间问题主要在于缓存,占用空间小的索引可以更多地被读入缓存,在查询时除了叶子节点都可以在内存中进行,避免了磁盘IO。时间问题主要在于创建索引和维护索引的开销。在OLTP应用中,时间问题相对空间问题更加突出。

索引的创建开销

在线上环境中添加索引中是一件颇具风险的事。创建索引时需要锁或者需要创建临时表,这将使得数据表在索引创建期间可用性大大降低。

InnoDB通过Online DDL来改善这种情况,Online DDL视情况给表添加共享锁或者排它锁复制来添加索引,对于添加索引期间的更新操作写入到一个缓存中,待索引创建完成后再将操作应用到表上达到一致性。

索引的维护开销

每向数据表插入一行数据,都需要更新表上所有的索引,如果是唯一性索引还需要提前做唯一性检查;每更新一列带有索引的列,都需要更新索引顺序。这些使得更改操作时间开销增加。

不同于聚集索引,辅助索引的更新操作更多是随机磁盘访问,开销较大。InnoDB引入了Insert Buffer来提高辅助索引的更新性能。每次更新索引页时,如果该索引页已经被读入内存缓存,可以直接更新;如果没有读入,则将更新写入Insert Buffer而不是写回磁盘,然后再周期性地合并更新操作一起写回磁盘,减少了磁盘IO次数,提高了辅助索引更新的性能。但是Insert Buffer不能用在唯一索引上,因为需要访问磁盘做唯一性检查。

基于索引的维护开销,在创建辅助索引时需要综合考虑,盲目添加索引可能给系统增加不必要的负担。

索引的使用
Cardinality值

Cardinality值表征了索引列值的离散程度,Cardinality值越接近记录总数,离散程度越高,反之越低。离散程度高的列数据选择性高,通过索引容易定位某一行,反之选择性低,索引查找出来还是有很多行,需要线性遍历,开销很大。
InnoDB的Cardinality值是通过采样8个索引页估算的,并不完全精确。

联合索引

联合索引的键值排序是先依照第一列排序,第一列元素相同的依照第二列排序…依此类推,所以在使用联合索引时,如果条件不包含前面的列,将无法确定元素在索引中的位置,因而也无法使用索引

联合索引对索引列依次排序,在查询含有ORDER BY的SQL时,如果ORDER BY的字段在联合索引中,将节省查询时间。

短索引

某个字段长度较长,但其前面几个字符的离散程度已经比较高了,可以只在其前面几个字符上建立索引,一方面减少排序的计算量,一方面减少索引的大小,可以更多地被读入内存缓存,减少索引读取的磁盘IO。

覆盖索引

如果需要的信息从辅助索引中就可以直接查询出来,而不需要回主键索引再次查询行数据,则直接通过辅助索引返回数据,效率更高。

MRR

由辅助索引查询出来的主键数据是依照索引列排序的,MRR先将这些主键数据按照主键顺序排序,然后再去主键索引中查询行数据,变随机读取为顺序读取,提高IO效率。

其他不使用索引的情况
  • like以%开头
  • 条件中对索引列有计算(函数计算、数学计算、类型转换)
  • 优化器认为全表扫描效率更高(多见于范围查找【范围查找全表扫描可以顺序读,索引的随机读效率并不一定高】)

MySQL技术内幕 InnoDB存储引擎 第2版
https://blog.csdn.net/voidccc/article/details/40077329
https://blog.csdn.net/kaka1121/article/details/53395628

猜你喜欢

转载自blog.csdn.net/john_lw/article/details/80309952
今日推荐