前提条件 有一个数据列不会有重复数据现在需要选择创建索引,我们应该如何去选择呢?
1.普通索引
查找时,遇第一个不符合条件的才返回。
更新时,找到位置直接更新
2.唯一性索引
查找时,遇到第一个符合条件的直接返回。
更新时,先查找是否唯一,再找到位置然后再更新。
我们来通过底层分析一下:
Select:
*
我们都知道一个索引就是创建一个B+树,如果他是一个普通索引我们现在去查找,当查找到符合的数据的时候这个时候他就会在进行第二次查找,因为列里面的数据是唯一的,所以第二次查找肯定是没有数据的,这一次查找通过二分法去查找B+树查找到二叉树的叶子结点,每个叶子结点都会对应一个数据块(数据页),如果这个数据页在内存中那么他也就不用去在磁盘或硬盘去读区这个数据了,直接在内存中读取,我们也知道一个数据块大概是可以存储几千条数据的,所以在第一次查找的时候刚好这个数据块的尾部,在进行第二次查找的时候就要在进行IO读取了
一次IO读取是很低效的。但是如果是唯一索引的话这样的话就不会再进行第二次读取了,所以在最坏的情况下,普通索引和唯一索引的最大区别是多进行一次IO读取,概率极小。
update:
2.在update或者insert的时候普通索引也就是去在B+ 树中去找位置然后按照B+树的算法结构更新放入
或者更新其结构(拓展:在创建索引的时候会降低更新和插入效率,因为B+树在某种情况下添加结点效率会比较低),这在innoDB中如果说是在内存中没有这个数据块那么在这个情况下他不会去现在就去更新,会将这个更新操作存储在ChangeBuffer上,当第二次有查找这个数据的时候再去读取这个数据块然后再执行这个ChangeBuffer
中的数据操作,meger
这个数据。(在redlog里面也会存一份,也会存储changeBuffer的才操作数据,ES(Elaticsearch)的一种同步方式是通过redo log
来进行是实时同步的),当唯一索引进行更新操作的时候
会先进行一次查找是否唯一,再进行和普通索引一样的操作。所以在符合业务逻辑和无误的前提下:唯一索引比普通索引多一个查找操作。(在进行insert的时候会根据主键来进行查住
主键索引的数据结构发生改变)
通过上面的描述: 在符合业务场景的前提下的时候唯一索引还是少用多用用普通索引。 还有就是change Buffer的使用 在更新读取少的
情况下放大change buffer的存储量 因为chanbuffer量越大其变更的数量更多 减少的IO次书更多,性能也就提高了。