09 | 普通索引和唯一索引,应该怎么选择
09 | 普通索引和唯一索引,应该怎么选择
查询过程的区别
- 对于普通索引来说,查到满足条件的第一个记录,再查找下一个记录,直到查到一个不满足条件的记录,结束。
- 对于唯一索引来说,查找到满足条件的第一个记录,结束。
普通索引的查找过程看似比唯一索引多了几步,但考虑到索引的数据模型是B+树,且数据都是按页读取的,所以多出来的几步操作对象都是内存,性能影响可以忽略不计。
恰巧处于数据页边缘的情况也会存在,但是几率太小了,也可以忽略不计
change buffer使用区别
更新操作时,如果要被更新的数据页已经在内存中,直接更新即可。如果数据页不在内存中,此时会把更新操作先计入change buffer中,等到对应的数据页被访问的时候,再将其读入内存,和change buffer做一个merge操作,保证数据的正确性(当然系统也会有后台线程定期做merge操作)。
唯一索引的更新无法使用change buffer,因为每次更新都需要先判断是否违反唯一性约束,这需要把数据读入内存。
change buffer需要单独总结一篇,参考
普通索引和唯一索引的更新过程
- 要更新的目标页在内存中
- 唯一索引:找到指定的位置,判断没有冲突,则插入
- 普通索引:找到指定的位置,插入
- 要更新的目标页不在内存中
- 唯一索引:将数据页读入内存,判断有无冲突,没有冲突则插入
- 普通索引:将更新操作记录到 change buffer,结束
由此可见,普通索引的更新性能更好。
change buffer 的使用场景
仅限于普通索引,不适用于唯一索引
普通索引的所有场景,change buffer 都能起到加速作用吗?
change buffer 的主要原理是在更新操作时,减少了一次读磁盘的IO:数据不在内存,先记下更改,等下次读它的时候再顺便把更新做了(merge操作)。由此可知,在数据页做merge之前,change buffer 记录的变更越多越好。所以结论如下:
- 对于写多读少的业务,change buffer 使用效果最好
- 对于读多写少的业务,change buffer 会起到反作用
change buffer 与 redo log
redo log 主要节省的是随机写磁盘的 IO 消耗(转成顺序写),而 change buffer 主要节省的则是随机读磁盘的 IO 消耗
问题讨论
change buffer 一开始是写内存的,那么如果这个时候机器掉电重启,会不会导致 change buffer 丢失呢?change buffer 丢失可不是小事儿,再从磁盘读入数据可就没有了 merge 过程,就等于是数据丢失了。会不会出现这种情况呢?
答案 不会丢失。虽然是只更新内存,但是在事务提交的时候,我们把 change buffer 的操作也记录到 redo log 里了,所以崩溃恢复的时候,change buffer 也能找回来