专业书籍精读 · Database Internals · 第 6 章

B-Tree 变体

Database Internals · Ch 6 · Alex Petrov · 2019

EN →

这一章讲什么?

前几章把数据库那本「目录」建好了:一层层的路标,几步就翻到你要的那一页。这一章问的是另一件事——这套办法是四十年前为机械硬盘、单核机器想出来的,今天还合身吗?

先说个怪事

你大概以为,数据库的贵在于「找」。其实贵在「改」。你改一条八十个字的记录,硬盘上至少要重写一整页(几千到上万个字);而且为了别人不会读到一张改到一半的纸,这页上还得挂个「施工中」的牌子——谁路过谁等。找一条记录只要翻三四页,改一条记录却要重抄一页、还要让路人排队。

旧世界为什么难

一,改一个字,重写一整页。页是硬盘的最小单位,改一个字节和改一整页花的力气差不多。

二,「施工中」的牌子挂在越上面越堵。目录树的最顶上那一页人人都要路过,它一挂牌,整台机器的几十个核就一起排队。

三,原地涂改本身就危险。正把一页覆盖到一半断电,这页就成了半旧半新的乱码——上一章那本流水账,一多半就是为了给这种「涂改」擦屁股。

核心机制:四种「别在原稿上涂改」的办法

一、誊清而不涂改。要改哪一页,不动原稿,抄一张新的、在新纸上改;从封面到那一页的一路路标也跟着重抄,最后把目录第一行指向新版本——换指向是一瞬间的事,要么旧要么新,没有中间态。正在读旧版本的人完全不受影响,读者永远不必排队。

二、先贴便签,攒够了再誊。不必每改一次就重抄整页,先在页边贴一串便签写「这行改成了什么」,读的人把原页和便签合起来看;便签攒多了再一次性重抄成干净的一页。

三、分层归档。新改动先进最上面那本薄册子,薄册子满了就整本并进下面更厚的一本,一层层往下。每本册子做好就不再改,写下去全是一口气顺着写——固态盘最喜欢这样,最怕东一处西一处地零敲碎打。

四、大家只认门牌号,不认地址。所有指路的地方都写门牌号,另有一本「门牌号 → 现在的地址」的登记簿。要改某一页,就写一张「改动条」贴在原页上,再把登记簿那一行改指向它——改一行登记簿是不可分割的瞬间动作,谁都不用挂牌、不用排队。

带来了什么 / 该怎么选

这四招各治一个病:誊清治「怕断电、读者排队」,便签治「改一个字重写一页」,分层归档治「固态盘怕零散写」,门牌号治「排队」。代价也都长得像:新版本写出来了,旧版本得有人打扫——省下的写,往往变成多占的空间和一堆后台整理的活。

一句话记住

经典的目录树贵在改,不在找。这一章的四个变体全在拆同一个假设——非得在原地涂改不可吗?不涂改,改成誊清一份、贴便签攒着、分层归并、或者只追加一张改动条再换个门牌指向;换来的是不怕断电、读者不排队、对固态盘友好,付出的是空间和一份没完没了的打扫工作。

想进到具体机制、记号和示意图? → 切到精读版