持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情
前言
比如说在设计一张用户表时,每个人的手机号是唯一的,需要搜索,在业务代码能够保证插入的手机号是唯一的情况下,可以选择建立唯一索引和普通索引,那么这时我们选择普通索引还是唯一索引性能更好呢?下面我们就从两种索引对查询过程和更新过程的性能影响来分析。感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
唯一索引和普通索引区别
我们可以先来看下二者的区别;
普通索引
顾名思义最为普通的索引,主要任务是提高查询速度。允许出现相同的值,允许空值。
唯一索引
索引列中的值必须是唯一的,但是可以允许为空(null)值。主键索引是唯一索引的特定类型。
性能分析
从查询角度分析
对于一条查询语句比如:
select * from user where phone = '187xxxx0001';
查询过程为,先通过B+树从树根开始,按层搜索到叶子节点,然后再进行判断:
- 对于普通索引来说,查找到满足条件的
phone之后,需要再去查找下一个记录,直到碰到phone不符合要求的记录。 - 对于唯一索引,由于索引保证了唯一性,查找到第一个符合条件的
phone之后就会立即返回,不再进行检索了。
以在这里的区别就是普通索引会多查那么一下,因为mysql在读数据的时候,磁盘会按照页为单位读取数据到内存中,在读入内存的数据页中找到符合条件的phone这一条记录,在查询的情况下,普通索引比唯一索引多了一次查找和判断的过程,可以忽略。所以总得来说,普通索引和唯一索引在查询的过程中差异不大。
从更新角度分析
对于一张表插入一个新记录:
如果新记录要更新的数据页在内存中:
- 对于唯一索引,找到合适的位置,判断有没有冲突,插入值,语句结束。
- 对于普通索引:找到位置,插入值,语句结束。
所以数据页在内存时,唯一和普通索引就差一个判断的过程。可以忽略。
如果新记录要更新的数据页不在内存中:
- 对于唯一索引,将数据页读入内存,判断冲突,插入,语句结束。
- 对于普通索引,将语句记录在 change buffer 中,语句结束。
由于从磁盘到内存涉及随机 IO 访问,是数据库成本最高的操作之一。普通索引比唯一索引减少的读入操作,可以有很好的性能提升。
小结
本文通过对普通索引和唯一索引的对比,了解了数据的查询和更新过程,两类索引在查询能力上没有什么差别,主要考虑的是对更新性能的影响。如果业务能保证一个字段的唯一性并且针对的是写多多少的业务模式,从性能角度出发建议优先考虑那么还是选择普通索引的好。