你分得清MySQL普通索引和唯一索引了吗?( 三 )


要读Page2时 , 需把Page2从磁盘读入内存 , 然后应用change buffer里面的操作日志 , 生成一个正确版本并返回结果 。 可见直到需读Page2时 , 该数据页才被读入内存 。
所以 , 要简单对比这俩机制对更新性能影响

  • redo log 主要节省随机写磁盘的IO消耗(转成顺序写)
  • change buffer主要节省随机读磁盘的IO消耗
6 总结由于唯一索引用不了change buffer的优化机制 , 因此如果业务可以接受 , 从性能角度 , 推荐优先考虑非唯一索引 。
6.1 关于到底是否使用唯一索引主要纠结在“业务可能无法确保” 。 本文前提是“业务代码已经保证不会写入重复数据”下 , 讨论性能问题 。
  • 如果业务不能保证 , 或者业务就是要求数据库来做约束 , 那么没得选 , 必须创建唯一索引 。 这种情况下 , 本文意义在于 , 如果碰上大量插入数据慢、内存命中率低时 , 多提供一个排查思路 。
  • 然后 , 在一些“归档库”的场景 , 可考虑使用唯一索引的 。 比如 , 线上数据只需保留半年 , 然后历史数据保存在归档库 。 此时 , 归档数据已是确保没有唯一键冲突 。 要提高归档效率 , 可考虑把表的唯一索引改普通索引 。
6.2 如果某次写入使用change buffer , 之后主机异常重启 , 是否会丢失change buffer的数据?不会丢失 。 虽然是只更新内存 , 但在事务提交时 , 我们把change buffer的操作也记录到redo log , 所以崩溃恢复时 , change buffer也能找回 。
6.3 merge的过程是否会把数据直接写回磁盘?merge执行流程
  1. 从磁盘读入数据页到内存(老版本数据页)
  2. 从change buffer找出该数据页的change buffer 记录(可能有多个) , 依次应用 , 得到新版数据页
  3. 写redo log该redo log包含数据的变更和change buffer的变更
至此merge过程结束 。 这时 , 数据页和内存中change buffer对应磁盘位置都尚未修改 , 是脏页 , 之后各自刷回自己物理数据 , 就是另外一过程 。