普通索引的性能会不会比唯一索引好?

普通索引和唯一索引的区别就是,普通索引的字段内容是可以重复的,唯一索引的字段内容不可重复。

一、查询过程

假设查询语句为select id from test where k=10;首先会通过B+树的树根开始按层搜索叶子节点,找到对应的数据页后,在页内进行二分查找定位记录。

  • 对于普通索引,查找到第一条符合条件的记录(id,10)之后,继续往后查找,直到找到第一条不满足k=10的记录
  • 对于唯一索引,查找到第一条符合条件的记录(id,10)之后,直接返回结果

唯一索引定义了唯一性,有且只有一条符合条件的记录,普通索引则可能存在多条记录

这两种情况下,性能会相差多少?

我们知道,InnoDB中的数据是按数据页为单位进行读写的,也就是说,当找到K=10的那条记录,包含这条记录的数据页已经在内存中,并且是顺序读取,读取一条记录和读取多条记录,性能相差不了多少。当然,如果刚好要读取的下一条记录在下一个数据页,花费的时间会长一点,但是这是小概率事件。 总而言之,对于查询过程,普通索引和唯一索引的效率相近

二、更新过程

1. change buffer

当需要更新某个数据页时,有两种情况:

  • 数据页在内存中:直接更新,该数据页标记为脏。
  • 数据页不在内存中,把更新操作缓存在change buffer当中,在下次需要读取这个数据页时,把该数据页加载到内存,并且把change buffer中的更新操作应用到数据页中,以此保证数据的一致性。

change buffer是可持久化的数据,会写入到磁盘

2、merge

将change buffer中的操作应用到原始数据页的过程称为merge。 触发merge的情况有以下几种:读取该数据页、系统后台定期merge、数据库正常关闭。

显然,将更新语句缓存在change buffer的好处有两个:1、减少磁盘的IO次数,语句执行速度提升;2、减少数据页读入内存,提高内存利用率;

3、使用场景

当然,并不是任何情况下使用change buffer都会提升性能的。

唯一索引还是普通索引?

对于唯一索引,每次对数据的更新都需要先把数据页加载到内存,判断是否违反唯一性约束,而对于已经在内存当中的数据页,是否随机读写已经不重要了,也就没有必要使用change buffer缓存更新操作。

对于普通索引,由于不需要数据页在内存中判断唯一性约束,可以缓存更新操作,减少了对磁盘的随机IO次数。

普通索引就可以了吗?

如果业务场景是写后需要立即读取,change buffer还有优势吗?

更新操作写入change buffer后,由于需要马上读取,也就是立即触发了merge过程,这种情况下磁盘的随机IO次数并不会减少,甚至还额外增加了change buffer的维护成本。

也就是说,change buffer适用于写多读少的场景,这样才能在下一次merge之前缓存更多的更新操作,收益才更大。这种业务模型常见的就是账单、日志等系统。

三、change buffer和redo log

redo log是WAL机制的核心,提升性能的手段是减少对磁盘的随机写的IO消耗;而change buffer减少的是对磁盘的随机读的IO消耗

Guess you like

Origin juejin.im/post/7040110129512972325