Nan.fyiのチュートリアルは、データベースという発想を一連の実践的なエンジニアリング上のトレードオフとして捉えている。完成したシステムから出発するのではなく、キー・バリュー・ストアをゼロから作らなければならない場合、どのように構築するかを問いかける。その答えは段階的に示される。データをファイルに永続化し、更新を追記専用にし、削除用のトゥームストーンを追加したうえで、システムを実用可能にするためにコンパクションとインデックスを導入する。
最初の教訓は、単純な永続化は想像しやすいものの、実際には非効率だということだ。レコードを順番に書き込み、ファイル全体をスキャンして検索するなら、挿入は単純だが、更新と削除はすぐに高コストになる。1つのレコードを変更するだけで、後続のバイトを移動しなければならない可能性があり、ファイルが大きくなると、その場での編集は非現実的になる。
このガイドが次に取る手法は、レコードをイミュータブルとして扱うことだ。古いエントリーを書き換える代わりに、データベースは新しいバージョンをファイルの末尾へ追記する。削除は、そのキーが削除されたことを示す特殊なマーカーで表現される。この方法は書き換えの問題を解決するが、別の問題を生む。古くなったデータが蓄積し、重複または無効なエントリーによってファイルが増大するのだ。
その答えがコンパクションだ。ファイルがしきい値に達すると、システムはそのファイルへの書き込みを停止し、新しいセグメントを作成したうえで、古くなったレコードを破棄して以前のファイルを整理できる。これはよく知られたストレージのパターンであり、データベースが新しいデータを取り込み続けながら、不要な部分を徐々に縮小できる。このガイドは、後からセグメント同士を統合できるとも指摘しており、それによって規模が拡大してもストア全体を管理可能に保てる。
検索には別のボトルネックがある。ルックアップのたびにファイル全体をスキャンするのは遅すぎるため、チュートリアルは、キーをファイル内のバイトオフセットに対応付けるインメモリー・ハッシュテーブルを導入する。これによって読み取りは大幅に高速化するが、トレードオフも明らかになる。インデックスは、挿入、更新、削除のすべてと同期させなければならない。検索の高速化には、書き込みの低速化と追加の管理作業が伴う。
そこから記事は、ソート済みストレージと範囲クエリーへ話を進め始め、データベースはすべてを一度に置き換えるのではなく、構造を積み重ねることで進化できることを示す。このガイドの有益な点の一つは、それぞれの改善を特定の障害モードへの対応として扱っていることだ。追記専用ストレージはある種類の問題を解決し、インデックスは別の問題を解決し、コンパクションはファイルの増大に対処し、ソートはより効率的なクエリーへの道を開く。
その結果、データベースのインターフェースの背後に隠れたままになりがちな仕組みを、分かりやすく一巡できる内容となっている。ファイルとハッシュテーブルだけで本番環境に対応できると装ってはいない。代わりに、現実のストレージエンジンが、耐久性、書き込み速度、読み取り速度、保守の間で重ねられた一連の妥協によって形作られている理由を示している。
上位レベルのソフトウェアを通じてしかデータベースを使わない読者にとって、この記事は、単純な`get`や`put`の一つ一つが、幾層ものトレードオフの上に成り立っていることを思い起こさせる。要点は、単におもちゃのデータベースを作ることではない。成熟したシステムがなぜ現在の形をしているのか、またフラットファイルから信頼できるストアへ至る道筋が、通常はなぜ追記専用ログ、トゥームストーン、インデックス、コンパクションを経由するのかを理解することにある。



