一、唯一索引和普通索引的选择(Mysql实战45讲笔记-实践)

1.唯一索引和普通索引

1. 1 查询过程中的不同

在索引树查询的过程,通过B+树从树根开始,按层搜索到叶子节点。

比如select id from T where k=5,搜索到的就是下图中右下角的数据页,然后可以认为数据页内部通过二分法来定位记录。

image-20210413141521506

  • 普通索引:查找到满足条件的第一条记录后,接着搜索下一个记录,知道第一个不满足k=5条件的记录。
  • 唯一索引:查找到第一条满足条件的记录后,就会停止检索

两者的性能差距不大,因为InnoDb的数据是按照数据页为单位来读写的,一个数据页的大小默认是16k,数据页是整体读到内存的,所以对于两种索引的搜索性能差别不大。

极特殊情况下,满足条件的记录是数据页最后一条记录,那普通索引在搜索下一个记录的时候,会读下个数据页的数据,这种情况下,普通索引的效率会高一些,不过对于整型字段,一个数据页可以放近千个key,所以满足条件的记录在数据页最后的概率比较低。

1.2 更新过程中的不同

1.2.1 change buffer 简介

唯一索引和普通索引在更新过程的差异,主要在于change buffer。首先解释一下什么是change buffer。

  1. 更新数据的步骤,两种情况:
    1. -> 数据所在的数据页在内存中 -> 直接更新内存
    2. -> 数据所在的数据页不在内存中 -> 将更新操作缓存在change buffer 中
  2. 查询上个步骤更新的数据 -> 将数据页读入内存 -> 根据change buffer中存储的操作,更新内存。

将change buffer中的操作应用到原数据页,得到最新的结果的过程称为merge

触发merge的三种情况:

  1. 通过访问这个数据页触发merge
  2. 系统后台线程也会定期meger
  3. 数据库正常关闭(shutdown)的时候也会merge

注意:

  1. change buffer 是可以持久的数据,它在内存中有拷贝,也会写在磁盘中
  2. change buffer 占用的是buffer pool的内存,通过设置 innoDB_change_buffer_max_size参数,来设置占用buffer pool内存大小比例,如设置50,则占用50%
  3. 通过将更新操作记录到change buffer,减少读磁盘,提高语句的执行效率,而且数据读入内存,也需要占用buffer pool ,这样也减少了内存占用

1.2.2 普通索引和唯一索引更新步骤

chang buffer 也不是适用所以场景,可以提高效率的。

例如唯一索引的更新操作,都会在更新操作前判断是否违反唯一性,所以先要进行读操作,这样更新数据的时候,就可以直接更新内存,就用不到change buffer了。

插入数据不同情况下,唯一索引和普通索引的插入步骤:

  1. 要更新的目录也在内存中:
    • 唯一索引:找到位置后,判断没有冲突后插入,结束
    • 普通索引:找到位置后,插入,结束
  2. 要更新的目录不在内存中:
    • 唯一索引:将数据页加载到内存中,判断没有冲突后插入,结束
    • 普通索引:将更新操作记录到change buffer,结束

将数据从磁盘读入内存涉及随机IO的访问,是数据库中成本最高的操作。所以普通索引使用change buffer 减少了随机磁盘访问,对更新性能显著提高。

1.2.3 change buffer的使用场景

根据上一个小节,可以看到普通索引在更新的过程中使用change buffer,效率高于唯一索引的更新过程。但是普通索引也不是在所有情况下,通过使用change buffer可以提高性能的。

merge的时候,change buffer中存储的操作步骤越多,对于性能的提高越高

如果在进行更新操作后,马上又进行查询操作,就会马上触发merge,不但没有提高效率,还增加了维护change buffer的成本。

change buffer的适用场景:不会插入后马上去查询的场景,如日志类、账单类,

1.2.4 change buffer 和redo log

随后来补

原文地址:https://www.cnblogs.com/zhaoyuan72/p/14653415.html