9

InnoDB的缓存替换策略及其效果

 3 years ago
source link: https://blogread.cn/it/article/162?f=hot1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

InnoDB的缓存替换策略及其效果

浏览:3185次  出处信息

我们开发自己的存储引擎页面缓存替换策略的过程中主要是参考了InnoDB与LRU-K算法。InnoDB缓存替换策略使用分代与LRU相结合的方式。分为old和young两个分代,系统维护old分代占总buffer大小的3/8左右。当一个页面第一次被访问时,是加入到old分代的lru头。并不是每次访问一个页面时就将这个页提到lru的头部,而是在这个页面在LRU中的位置调整后,是否有很多页面已经被替换出去,若有,则将这个页面移到LRU头。系统在每个页记录调整该页在lru中位置当前系统总共替换了多少个数据页,比较页中记录的这个计数与系统全局页替换计数,就可以发现上次调整这个页在lru链表中位置后,系统中又有多少个页被替换,若比较多,则再次调整该页在lru中的位置。由于第一次访问的页被加入到old分代中,因此一次表扫描不会导致young分代中的页被替换出去。

    总的来说InnoDB的缓存替换策略非常简单,性能开销很低,但不知道其效果如何,因此今天进行了测试。测试时的表每条记录包含一个INT和两个CHAR(200)类型的字段,共20万条记录,其访问概率使用screw为1.2的Zip-f分布生成,这样访问概率最高的10%的记录的总访问概率为95%。表大小约占7000个页面,测试时设置InnoDB可用于存储数据的缓存页为730(InnoDB缓存大小必须设置为64个页的整数倍,无法精确控制到700个),约为数据量的10%。这时,理论上最优的缓存失配率应为5%。

    使用10个线程进行测试,每个进行100000次随机操作,每个操作根据概率随机访问一条记录。测试之前先进行了一次全表扫描来预热。

    测试之前各类读操作统计如下

| Innodb_buffer_pool_reads          | 77        |

    | Innodb_data_reads | 7004 |

    | Innodb_pages_read | 6994 |

    测试之后各类读操作统计如下

| Innodb_buffer_pool_reads          | 72055      |

    | Innodb_data_reads | 95197 |

    | Innodb_pages_read | 95187 |

如果按Innodb_buffer_pool_reads计算,即不考虑预读时,测试期间读取的页面数为72000左右,失配率为7.2%。如果按Innodb_pages_read计算,即考虑预读时,测试期间读取的页面数为88200左右,失配率为8.8%。如理想的5%相比两者都还是有一定距离的。若能优化到理想状态,大致可以减少40%的IO。

    同样的条件对比测试了一下,我们的存储引擎测试期间产生的读操作为62100次,稳定时的失配率为6.1%左右。目前还不清楚为什么我们的存储引擎为什么表现会比InnoDB要好,因为两者的策略是类似的。可能是因为InnoDB中的预读机制在这类纯随机的负载下反而会影响到缓存的命中率。由于Innodb_pages_read明显的超过Innodb_buffer_pool_reads的增长,可以看出测试过程中InnoDB也在不定的进行预读,有可能预读进来无用的页面,导致有用的页面被替换出去。我们的存储引擎的预读检测机制有所不用,在测试期间没有发生预读。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK