1 MySQL普通索引和唯一索引如何选择?
1 普通索引和唯一索引介绍
普通索引可重复,唯一索引和主键一样不能重复。
唯一索引可作为数据的一个合法验证手段,例如手机号、身份证号,规定该字段不得重复,那么就使用唯一索引。
唯一索引的作用跟主键一样,但区别:
一张表里面只能有一个主键,主键不能为空,但唯一索引可以有多个。唯一索引可以有一条记录为null。
2 查询性能分析
InnoDB数据按数据页单位读写。即读一条记录时,并非将该一个记录从磁盘读出,而以页为单位,将其整体读入内存。
例如(k,v)的表,查找k=4的记录:
普通索引
查找到满足条件的第一个记录(4,400)后,需查找下个记录,直到碰到第一个不满足k=4的记录
唯一索引
由于索引具备唯一性,查到第一个满足条件的,就会停止搜索
区别:普通索引,多了一次“查找和判断下一条记录”的操作,即一次指针寻找和一次计算。若k=4记录恰为该数据页的最后一个记录,则此时要取下个记录,还得读取下个数据页。
一般性能差距很小。
3 更新性能分析
插入一个新记录(4,400)
影响因素:该记录要更新的目标页是否在内存
在内存
- 普通索引
找到3和5之间的位置,插入值,结束。 - 唯一索引
找到3和5之间的位置,判断到没有冲突
,插入值,结束。只是一个判断的差别,耗费微小CPU时间。
不在内存
- 普通索引
将更新记录在change buffer,结束。 - 唯一索引
将数据页读入内存,判断到没有冲突,插入值,结束。 - 将数据从磁盘读入内存涉及随机I/O访问,是DB里成本最高的操作之一。而change buffer可以减少随机磁盘访问,所以更新性能提升明显。
4 索引选择的最佳实践
普通索引、唯一索引在查询性能上无差别,主要考虑更新性能。所以,推荐尽量选择普通索引。
若所有更新后面,都紧跟对该记录的查询,那就该关闭change buffer(如果更新和查询操作的时间间隔较短,那么关闭Change Buffer也不会对查询性能造成太大的影响,因为这时候查询的数据可能还在磁盘缓存中,可以快速地被查询到)。其它情况下,change buffer都能提升更新性能。
普通索引和change buffer的配合使用,对于数据量大的表的更新优化还是明显的。
在使用机械硬盘时,change buffer的收益也很大。
所以,当你有个类似“历史数据”的库,并且出于成本考虑用机械硬盘,应该关注这些表里的索引,尽量使用普通索引,把change buffer 开大,确保“历史数据”表的数据写性能。
5 推荐
由于唯一索引用不了change buffer,若业务可以接受,从性能角度,优先考虑非唯一索引。
6 到底何时使用唯一索引
如果业务代码已经保证不会写入重复数据,则可以尽可能考虑普通索引
如果业务不能保证或业务就是要求数据库来做约束,必须创建唯一索引。
“归档库”场景,可考虑使用唯一索引
比如,线上数据只需保留半年,然后历史数据保存在归档库。此时,归档数据已是确保没有唯一键冲突。要提高归档效率,可考虑把表的唯一索引改普通索引。