普通索引和唯一索引优化:

11.1 查询过程
假设,执行查询的语句是 select id from test where k=5。
对于普通索引来说,查找到满足条件的第一个记录(5,500)后,需要查找下一个记录,直到碰到第一
个不满足k=5条件的记录。
对于唯一索引来说,由于索引定义了唯一性,查找到第一个满足条件的记录后,就会停止继续检
索。
那么,这个不同带来的性能差距会有多少呢?答案是, 微乎其微 。

11.2 更新过程
为了说明普通索引和唯一索引对更新语句性能的影响这个问题,介绍一下change buffer。
当需要更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,
在不影响数据一致性的前提下, InooDB会将这些更新操作缓存在change buffer中 ,这样就不需要从磁
盘中读入这个数据页了。在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行change
buffer中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性。
将change buffer中的操作应用到原数据页,得到最新结果的过程称为 merge 。除了 访问这个数据页 会触
发merge外,系统有 后台线程会定期 merge。在 数据库正常关闭(shutdown) 的过程中,也会执行merge
操作。
如果能够将更新操作先记录在change buffer, 减少读磁盘 ,语句的执行速度会得到明显的提升。而且,
数据读入内存是需要占用 buffer pool 的,所以这种方式还能够 避免占用内存 ,提高内存利用率。
唯一索引的更新就不能使用change buffer ,实际上也只有普通索引可以使用。
如果要在这张表中插入一个新记录(4,400)的话,InnoDB的处理流程是怎样的?

11.3 change buffer的使用场景:只能使用于普通索引

  1. 普通索引和唯一索引应该怎么选择?其实,这两类索引在查询能力上是没差别的,主要考虑的是
    对 更新性能 的影响。所以,建议你 尽量选择普通索引 。
  2. 在实际使用中会发现, 普通索引 和 change buffer 的配合使用,对于 数据量大 的表的更新优化
    还是很明显的。
  3. 如果所有的更新后面,都马上 伴随着对这个记录的查询 ,那么你应该 关闭change buffer 。而在
    其他情况下,change buffer都能提升更新性能。
  4. 由于唯一索引用不上change buffer的优化机制,因此如果 业务可以接受 ,从性能角度出发建议优
    先考虑非唯一索引。但是如果”业务可能无法确保”的情况下,怎么处理呢?
    首先, 业务正确性优先 。我们的前提是“业务代码已经保证不会写入重复数据”的情况下,讨论性能
    问题。如果业务不能保证,或者业务就是要求数据库来做约束,那么没得选,必须创建唯一索引。
    这种情况下,本节的意义在于,如果碰上了大量插入数据慢、内存命中率低的时候,给你多提供一
    个排查思路。
    然后,在一些“ 归档库 ”的场景,你是可以考虑使用唯一索引的。比如,线上数据只需要保留半年,
    然后历史数据保存在归档库。这时候,归档数据已经是确保没有唯一键冲突了。要提高归档效率,
    可以考虑把表里面的唯一索引改成普通索引。