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 到底何时使用唯一索引

如果业务代码已经保证不会写入重复数据,则可以尽可能考虑普通索引

如果业务不能保证或业务就是要求数据库来做约束,必须创建唯一索引。

“归档库”场景,可考虑使用唯一索引

比如,线上数据只需保留半年,然后历史数据保存在归档库。此时,归档数据已是确保没有唯一键冲突。要提高归档效率,可考虑把表的唯一索引改普通索引。


1 MySQL普通索引和唯一索引如何选择?
https://leellun.github.io/2023/04/07/面试题/2-MySQL普通索引和唯一索引如何选择?/
作者
leellun
发布于
2023年4月7日
许可协议