普通索引和唯一索引,应该怎么选择?

104 阅读3分钟

查询过程

假设,执行查询语句是 select id from T where k = 5。这个查询语句在索引树上的查询的过程,先通过B+树从树根开始,按层搜索到叶子结点,也就是图中右下角的这个数据页,然后可以认为数据页内部通过二分法来定位记录。

1:对于普通索引来说,查找到满足的条件第一个记录后,需要查找下一个记录,知道碰到不满足的条件的记录。

2:对于唯一索引来说,由于索引定义了唯一性,查找到第一个满足条件的记录后,就会停止继续检索。 那么,这个不同带来的性能差距会有多少呢?答案是,微乎其微。

你知道的,innodb的数据是按照数据页的单位来读写的。也就是说,当需要读取一条记录时候,并不是将这个记录本身从磁盘中读出来,而是以页为单位,将其整体读入内存。在innodb中,每个数据页的大小默认是16KB。

更新过程

change buffer:当需要更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,innodb会将这些更新操作缓存到change buffer中,这样就不需要从磁盘中读入这个页数据了。在下一次查询需要访问这个数据的时候,将数据页读入内存,然后执行change buffer中与这个页有关的操作。

将change buffer中的操作应用到元数据页,得到最新结果的过程称为merge。除了访问这个数据页会出发merge外,系统有后台线程会定期merge。在数据库正常关闭过程中,也会执行merge操作。

什么条件下可以使用 change Buffer呢?

对于唯一索引来说,所以的更新操作都会先判断这个操作是否违反唯一约束。比如,要插入一行记录,这个要判断现在表中已经存在这条记录,而这必须要讲数据页读入内存中才能判断。如果已经在内存了,那就更新内存就更快,就没有必要使用change buffer了。

唯一索引的更新就不能使用到 change buffer,实际上也只能普通索引使用。

change buffer 用的是 Buffer pool里的内存,因此不能无限增大。change buffer的大小可以同参数 Innodb_change_buffer_max_size来动态设置,这个参数设置为50的时候,表示change buffer的大小最多占用 buffer pool的50%。

change buffer的使用场景

change buffer只限于用在普通索引的场景下,不适合用于唯一索引。

因为merge的时候是真正进行数据更新的时刻,而change buffer的主要目的就是将记录变更动作缓存下来,所以在一个数据页merge之前,change buffer记录变更越多,收益越大。