业务场景
在实际的业务中,一般都有用户信息表,而存储的数据包括(姓名、手机号、身份证号),对于业务层面来说一个人的身份证号是唯一确定的,所以在创建表的时候,针对身份证号列就可以选择创建普通索引或唯一索引。那么两者之间有什么区别?
不管是对于普通索引还是唯一索引,其实都是在索引树上的操作。一个是查询过程,另一个是更新过程。
查询过程
如果查询的语句是 select * from user where id_card = ‘11121212’, 普通索引和唯一索引的区别
其实就是是否会继续查询,因为对于INNODB来说数据是以页为单位存储的,所以当读入数据的时候根据局部性原理,相邻的数据也会加载。所以查询来说性能微乎其微,最多就是多几次指针查找和判断的处理。
更新过程
在说更新过程其实就需要介绍下change buffer的机制,一般来说 如果更新的数据页在内存中,那么直接就更新,如果不在内存中,为提升性能会先将数据更新到change buffer中,然后异步刷盘。(主要是查询、定期、shutdown 三个时机)。
接着说唯一索引,因为唯一索引具备唯一性,需要判断是否违反唯一性约束,所以需要将数据页读入内存,然后在判断,所以唯一索引没有办法使用change buffer来提升性能。
更新的目标页在内存中
- 对于唯一索引来说,会判断是否有冲突,没有冲突,直接执行。
- 普通索引,直接插入数据。
更新的目标页不在内存中
- 唯一索引,需要将数据页加载到内存中,然后判断没有冲突,插入这个值。
- 普通索引,将更新记录在change buffer中,语句执行结束。
所以总结下两者,可以发现对于不在目标页在内存中,会涉及到随机IO的访问,所以合理使用普通索引可以减少随机IO的访问,以及对更新性能的提升。
change buffer的使用场景
但是对于所有的普通索引场景来说,change buffer都可以提升更新过程的性能嘛,在整个性能瓶颈其实就是change buffer merge的过程,对于写多读少的场景,一般都是写入之后,一定时间内才会读取,比如每天的定时账单、对账记录等,比较合适。但是对于写多读多的场景,异步写到change buffer中,马上就来查询,那么就会触发merge的过程。
如何选择?
普通索引和唯一索引相比来说,查询没有什么区别,在更新上还是普通索引性能更好,建议选择普通索引。
show variables like '%innodb_change_buffer_max_size%';
redo log 主要节省的是随机写磁盘的 IO 消耗(转成顺序写),而 change buffer 主要节省的则是随机读磁盘的 IO 消耗。
小结
本篇主要介绍了普通索引和唯一索引的更新和查询的过程分析,如果业务层面可以保证数据唯一键,那么建议使用普通索引,否则的话可以采用唯一索引,由此引出了更新一个sql时,会操作的三大日志文件 undo、redo、bin log,通过上面这张图可以很直观的看出。