一些有趣的B+树优化实验(下)

卡瓦格博之巅
发布于 2022-8-2 18:06
浏览
0收藏

实验部分

在实验部分,作者通过前述的三个优化方法实现了一个新的B+树(命名为B-树以示区别),同时还实现了一个Baseline的B+树,并且与Rocksdb、WiredTiger做了比较全面的实验对比。


4.1 Experiments with Log-Flush-Per-Minute


在实验1中,Redolog的刷盘频率被设置为每分钟1次,以屏蔽掉Redo log写放大的影响。通过不同的数据集大小、单条记录的大小以及B+树页面大小设置,作者比较全面地评估了B-树的特性,得出初步的结论:B-树的写放大已经比较接近于LSM-tree,即右图中所有的橙色、绿色和紫色的部分比较接近。而Baseline B+tree和WiredTiger这两种标准的B+Tree,它们的写放大都比较大。


通过实验数据的对比,我们还可以发现:

  • B+树的写放大与Record size负相关,即Record size越小其写放大越大。以前面提到的极端例子为例,每条Record都会引起一次刷脏页,这时的写放大是Page size比Record size。如果Page size固定,当Record size越小,其写放大会越大。
  • B+树的写放大与并发数负相关,即并发数越大其写放大越小。我们可以理解为,当并发数比较高时,一个页面里可能会产生更多的更新,一次刷脏页就会有更多的Record进来。
  • LSM-Tree的写放大与数据集正相关。当数据集比较大时,做不同层之间的merge,它的写放大会变大。
    一些有趣的B+树优化实验(下)-鸿蒙开发者社区

    4.2 Experiments with Log-Flush-Per-Commit


    在实验2中,Redo log的刷盘频率被设置为每次事务提交,这也是我们在实际生产中为保证不丢数据而常用的方法。作者用一个单独的图来展示log部分的写放大,我们可以看到LSM-tree和B+树的Redo log的写放大都跟Record size相关,Record size越小,写放大越大,同时与并发数负相关,随着并发数的上升写放大会减小。这是由于并发数的上升实际上会产生更多日志的合并,即每次写盘时会有更多的事务的提交日志一起写入,因此写放大减少了。对B-树而言,由于采用了稀疏日志,所以其在不同Record size大小和不同并发数下都保持很小的日志写放大。


    图12展示了一个考虑日志写放大后的整体写放大。我们可以看到,B-树相对LSM-tree而言,它的写放大进一步降低,除了图中红框部分外,其他场景都比LSM-tree更优。

     

    一些有趣的B+树优化实验(下)-鸿蒙开发者社区

如果把两个不同的日志刷盘方式放在一起对比,我们可以发现,Redo log的写放大对B-树而言总体保持稳定,因为它使用了稀疏Redo log。当其他B+树和LSM-tree采用每事务提交时,两者的写放大显著提高,尤其是在并发数比较小的情况下,Redo log日志所引起的写放大占比较高。

 

一些有趣的B+树优化实验(下)-鸿蒙开发者社区

4.3 Impact of Threshold T


在实验3中,作者对算法2中提到的本地页面修改增量日志的算法做了验证。参数T表示当增量日志达到多少量时直接刷数据页面并重置增量日志,参数Ds表示页面分割的segment的大小。如图14和表格2,我们可以看到当T越大时,B-树的写放大会越小,但物理空间占用则会越大,这与我们之前的理论分析一致,所以这两个参数在实际中需要trade off。


图13展示了压缩对于物理空间占用的影响。由于B-树需要额外的4k页面占用,所以B-树的逻辑空间占用显著高于其他B+树,但在经过CSD压缩后,实际物理空间的占用放大则缩小了,相比B+树已经不明显了。

一些有趣的B+树优化实验(下)-鸿蒙开发者社区

4.4 Speed Performance Evaluation


在实验4中,作者对比了三种场景下的B-树相对于其他几种树的性能。


在随机点查场景中, B- tree 和 LSM-tree 相当,但两者都小于B+树。这与B- tree采用本地页面的增量日志刷脏页有关,因为每次读取需要重新通过增量日志来构造最新的数据页面,这会引入额外的开销 。


对随机范围查询而言,B-树和B+tree的性能相当,优于LSM-tree。作者认为,由于一次查询多条记录,B-树引入的读开销占比变小了,所以其性能比较高。


在随机写场景中,B-树稍微优于LSM-tree,两者都显著优于B+树,这是由于前两者都拥有更小的写放大。但需要强调的是,由于B-树和B+树都涉及到buffer 淘汰问题,所以虽然是只写负载但实际的IO却是读写混合的,因为B-树需要读取额外的4k增量日志页面,因此读IO比B+tree有所放大,其相对B+树的性能提升也就没有像写放大减少得那么显著。

一些有趣的B+树优化实验(下)-鸿蒙开发者社区

拓展与总结

最后分享一个CSD和PG结合起来的有趣实验。PG中有个名为 heap only tuple update的机制,用于优化非索引列更新。如下图所示,当更新一个元组时,如果当前元组所在的heap表页面有空闲空间,就可以直接在当前页面插入一条新的元组,再把老元组的ctid指向新元组即可,这样可以避免去找新的数据页面写入以及在索引页面中写入新的记录。PG中还有一个fillfactor的参数来控制heap表的填充率,我们可以利用较小填充率来换取非索引列更新的性能。当引入CSD之后,还可以进一步避免造成物理空间占用的放大,比较完美地解决了以往需要进行物理空间占用和性能trade off的问题

 

一些有趣的B+树优化实验(下)-鸿蒙开发者社区

综上所述,这篇论文提供了一个不同的视角去比较B+树和LSM-tree,让我们更深入地理解B+树和LSM-tree。作者通过三种实现比较简单但却非常巧妙的方法来改进B+树,在CSD上也取得了很好的效果,为我们带来了很好的启发。

 


参考文献

 

[1] Closing the B+-tree vs. LSM-tree Write Amplification Gap on Modern Storage Hardware with Built-in Transparent Compression

[2] The True Value of Storage Drives with Built-in Transparent Compression: Far Beyond Lower Storage Cost

[3] Understanding Flash: Blocks, Pages and Program / Erases

[4] B+Tree index structures in InnoDB

[5] PostgreSQL与透明压缩

[6] The Internals of PostgreSQL

[7] WiscKey: Separating Keys from Values in SSD-Conscious Storage

 

一些有趣的B+树优化实验(上)

 

 

文章转载自公众号:腾讯云数据库

 
 

分类
已于2022-8-2 18:06:44修改
收藏
回复
举报
回复