普通索引和唯一索引
选择普通索引还是唯一索引,需要从查询和更新两方面考虑。
1. 查询操作
索引上的查询,是从根结点开始,按层搜索到叶子节点,即所谓的数据页,然后在数据页内部使用二分法定位记录。
- 对于普通索引,先查找到满足条件的第一个记录,然后查找下一个记录,直到不满足条件。
- 对于唯一索引,只要查找到满足条件的第一个记录,就会停止继续检索。
InnoDB
数据是以页为单位从磁盘读写,数据页默认16k
。
对于普通索引,多做的一次查找和判断下一条记录操作,往往是在内存中进行。一次寻址和一次计算的消耗很小。
可以认为,普通索引和唯一索引的查询操作,性能差异可以忽略。
2. 更新操作
change buffer
更新一个数据时,如果数据在内存中就直接更新。
如果不在内存中,就会将更新操作缓存在change buffer
。查询操作访问该数据页时,会将数据页读入内存,然后对change buffer
进行merge
。
发生merge
的时刻:
- 访问数据页
- 后台定期
merge
- 数据库正常关闭时
merge
过程:
- 从磁盘读取数据页
- 应用该数据页的
change buffer
记录,得到新版数据页 - 写
redo log
,包含了change buffer
的变更和数据的变更
优点:
- 减少读磁盘
- 数据读入内存会占用
buffer pool
,所以可避免占用buffer pool
,提高内存利用率
唯一索引无法使用change buffer
:
唯一索引需要判断唯一性约束,因此需要将数据页读入内存。这时比起使用change buffer
,直接更新内存更快,
innodb_change_buffer_max_size
change buffer
使用的是buffer pool
里的内存。
大小通过innodb_change_buffer_max_size
参数控制。
比如设为50,表示change buffer
最多只能占用buffer pool
的50%。
插入新行
如果记录在内存中
对于唯一索引来说,需要判断唯一性冲突;对于普通索引来说,可以直接插入。多一个判断对性能基本没影响。
如果记录不在内存中
对于唯一索引来说,需要将数据页读入内存,从而判断唯一性。
对于普通索引来说,将更新记录记在change buffer
中即可。
change buffer
使用场景
普通索引才适用。
对于写多读少的业务,写完立马读取的概率小,可使用。
对于读取频繁的业务,写完之后马上读取,不会减少随机访问IO
的次数,还增加了change buffer
的维护代价。
redo log
和change buffer
redo log
节省随机写磁盘的IO
消耗,转成顺序写。
change buffer
节省的是随机读磁盘的IO
消耗。
近期评论