MySQL唯一索引和普通索引区别
唯一索引:唯一索引可以确保索引列不包含重复的值。在多列唯一索引的情况下,该索引可以确保索引列中每个值组合都是唯一的。
查询过程
比如查询id=5的数据
唯一索引:把数据读入磁盘,查询id=5的索引列就好了
普通索引:把数据读入磁盘,查找到满足条件的第一个记录 id=5 后,需要查找下一个记录,直到碰到第一个不满足 id=5 条件的记录。
更新过程
当需要更新一个数据页时,如果数据页在内存中就直接更新。
change buffer
而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InnoDB会将这些更新操作缓存在 change buffer中,这样就不需要从磁盘中读入这个数据页了。在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行 change buffer中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性。
第一种情况是,这个记录要更新的目标页在内存中。比如新增一条id=4的数据
唯一索引,找到 3 和 5 之间的位置,判断到没有冲突,插入这个值,语句执行结束;
普通索引,找到 3 和 5 之间的位置,插入这个值,语句执行结束。
第二种情况是,这个记录要更新的目标页不在内存中。这时,InnoDB 的处理流程如下:
唯一索引,需要将数据页读入内存,判断到没有冲突,插入这个值,语句执行结 束;
普通索引,则是将更新记录在 change buffer,语句执行就结束了。
将数据从磁盘读入内存涉及随机 IO 的访问,是数据库里面成本最高的操作之一。change buffer 因为减少了随机磁盘访问,所以对更新性能的提升是会很明显的。
change buffer业务场景
merge操作
需要说明的是,虽然名字叫作 change buffer,实际上它是可以持久化的数据。也就是说,change buffer在内存中有拷贝,也会被写入到磁盘上。将 change buffer 中的操作应用到原数据页,得到最新结果的过程称为 merge。
除了访问这个数据页会触发 merge 外,系统有后台线程会定期
merge。在数据库正常关闭(shutdown)的过程中,也会执行 merge 操作。
如果我们在业务场景中,是写多读少可以尽量使用普通索引(比如账单类、日志类的系统)。 但是如果我们写之后立马会进行查询,那么change buffer会立即触发 merge 过程。这样随机访问 IO 的次数不会减少,反而增加了 change buffer 的维护代价,这个时候普通索引就不是最好的选择了。