假如有一个系统,每个用户都有一个唯一的身份证号,那么这个字段设置为唯一索引还是普通索引呢?
下面分析查询和更新两个过程中,这两种索引对应效率的影响。
1、查询过程
1、假如执行查询的sql为select id from T where k=5。这个查询语句在索引树上查找的过程,先是通过B+树从树根开始,按层搜索到叶子节点,然后可以认为数据页内部通过二分法来定位记录。
对于普通索引来说,查找到满足条件的第一条记录后,需要查找下一条记录,直到碰到第一个不满足k=5条件的记录。
对于唯一索引来说,由于索引定义了唯一性,查找到第一个满足条件的记录后,就会停止继续索引
那么,这个不同带来的性能差距会有多少呢?微乎其微!
InnoDB的数据是按数据页为单位来读写的,也就是说,当需要读一条记录的时候,并不是将这个记录本身从磁盘读出来,而是以页为代为,将其整体读入内存,在InnoDB中,每个数据页的大小默认为16KB。
因为引擎是按页读写的,所以,当找到k=5的记录的时候,它所在的数据页就都在内存里了,那么对于普通索引来说,要多做的那一次查找和判断下一条记录的操作,就只需要一次指针寻找和一次计算。
当然,如果k=5这个记录刚好是这个数据页的最后一条记录,那么要取下一条记录,必须读取下一个数据页,这个操作会稍微复杂一些。但是,对于整形字段,一个数据页可以存放近千个key,因此出现这种情况的概率会很低,所以我们计算平均性能差异时,可以认为这个操作成本对于现在的CPU来说可以忽略不计。
2、更新过程
1、当需要更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InooDB会将这些更新操作缓存在change buffer中,这样就不需要从磁盘中读入这个数据页了。在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行change buffer中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性。
2、而实际上唯一索引的更新不能使用change buffer,实际上只有普通所以可以使用。