Author: 冷香
之前的月报中我们比较了InnoDB linear read-ahead和Oracle的multiblock read,两个的性能有所差别,具体可以参考月报详情。 这两种方式之所以带来了更高的吞吐量,都基于数据存储的连续性的假设,比如MySQL使用自增字段作为pk的InnoDB索引表,或者是Oracle使用默认的堆表,但当这样的假设条件不成立的时候,怎么办?
考虑下面的一个场景,如下图所示:
这是一个B-Tree结构,典型的InnoDB的索引聚簇表,这样的结构很容易构造,比如使用一个非连续的字段作为索引字段,随机对记录进行插入,这样leaf page链表上的page_no就会产生非连续性,如果进行一次全表扫描,比如 checksum table t
,按照正常的升序扫描,leaf page扫描的page_no顺序是3, 4, 5230等等,这样其实是无法使用到InnoDB 的Linear read-ahead,更没有办法合并IO请求。
对于存在时间比较长,变更又比较多的大表,除非我们对于这个表进行重建,否则leaf page的离散性会随着时间的推移,越来越严重。但对于在线应用来说,重建又会产生比较大的运维风险,这里就介绍一种平衡的方法,logical read-ahead。
逻辑预读的概念是指,根据branch节点来预读leaf节点。
逻辑预读使用两个扫描路径:
MySQL 5.6版本上的实现方式:
row_search_for_mysql
进行moves_up的过程中进行logical read-ahead;logical read-ahead很好的提升了离散存储数据的吞吐能力,Facebook在他们的MySQL实例的逻辑备份过程中,对于大表的dump备份开启了此特性,备份速度有非常大的提升。