我打算用类似于CouchDB的文件架构编写一个简单的键/值存储,即只附加b +树。
我已经阅读了我在B +树上可以找到的所有内容以及我在CouchDB内部可以找到的所有内容,但我没有时间通过源代码工作(使用非常不同的语言使其成为特别项目本身)。
所以我对B +树节点的大小有一个问题:给定的密钥长度是可变的,保持节点长度(以字节为单位)更好还是更好无论它们有多大,它们都有相同数量的键/子指针?
我意识到在传统数据库中,B +树节点以字节(例如8K)保持固定长度,因为数据文件中的空间是在固定大小的页面中管理的。但是在仅附加文件方案中,文档可以是任意长度并且更新后的树节点是在其后写入的,具有固定大小的节点似乎没有任何优势。
答案 0 :(得分:11)
b树的目标是最小化磁盘访问次数。如果文件系统簇大小为4k,则节点的理想大小为4k。此外,节点应正确对齐。未对齐的节点将导致读取两个群集,从而降低性能。
使用基于日志的存储方案,选择4k节点大小可能是最差的选择,除非在日志中创建间隙以改善对齐。否则,99.98%的时间将一个节点存储在两个集群上。如果节点大小为2k,则发生这种情况的可能性不到50%。但是,小节点大小存在问题:b树的平均高度增加,读取磁盘簇所花费的时间没有得到充分利用。
较大的节点大小会降低树的高度,但它们也会增加磁盘访问次数。较大的节点还会增加维护节点内条目的开销。想象一下b树,其中节点大小足以封装整个数据库。你必须在节点本身内嵌入一个更好的数据结构,也许是另一个b树?
我花了一些时间在仅附加日志格式上对b树实现进行原型设计,并最终完全拒绝了这个概念。为了补偿由于节点/群集未对齐而导致的性能损失,您需要具有非常大的缓存。更传统的存储方法可以更好地利用RAM。
最后一击是我评估随机排序刀片的性能。这会破坏任何磁盘支持的存储系统的性能,但基于日志的格式会受到更多影响。写入甚至最小的条目会强制将几个节点写入日志,并且内部节点在写入后不久就会失效。结果,日志迅速填满了垃圾。
BerkeleyDB-JE(BDB-JE)也是基于日志的,我也研究了它的性能特征。它遇到了我的原型所遇到的同样问题 - 垃圾的快速积累。 BDB-JE有几个“更干净”的线程,它们将幸存的记录重新附加到日志中,但保留了随机顺序。结果,新的“干净”记录已经创建了充满垃圾的日志文件。系统的整体性能降低到唯一运行的是清洁器,它占用了所有系统资源。
基于日志的格式非常有吸引力,因为可以快速实现强大的数据库。阿喀琉斯之踵是清洁工,非常重要。为了做到正确,缓存策略也很棘手。