世界を動かす技術を、日本語で。

データベースは本当に必要ですか?

2026年4月15日原文(dbpro.app)

概要

  • データベース は本質的に ファイル操作 で成り立つ
  • ファイル直書きとデータベース利用の パフォーマンス比較 を実施
  • 小規模アプリケーションでは 独自ファイル管理 も十分実用的
  • データベースが 必要になる条件 を明確化
  • ベンチマーク結果に基づいた 選択指針 を解説

データベースとファイルの本質

  • SQLite は単一ファイル、 PostgreSQL はディレクトリ+プロセス構成
  • どのデータベースも ファイルシステム への読み書きで動作
  • 問題は「ファイルを使うか」ではなく「 誰のファイルを使うか」という選択
  • 多くの初期段階アプリでは 自前ファイル管理 も十分に機能
  • DB Proのような 専用クライアント もあるが、導入判断は規模次第

ストレージ戦略の比較

  • 三つのファイル(users.jsonl, products.jsonl, orders.jsonl) を用意
    • 各ファイルは JSONL形式 (1行1レコード)で管理
  • エンドポイント はPOST /users(作成)とGET /users/:id(取得)のみ
  • アプローチ1:毎回ファイル全体を読む
    • リクエストごとにファイル全スキャン、 O(n) の計算量
    • ファイルが大きくなるほど遅くなる
  • アプローチ2:メモリ上に全データをロード
    • 起動時に全件を ハッシュマップ へ格納、書き込みは両方に
    • 読み込みは O(1)、高速化・並列化も容易
  • アプローチ3:ディスク上でバイナリサーチ
    • ファイルを ID順ソート +固定長インデックスを併用
    • O(log n) のディスクアクセスで目的レコードに到達
    • 追記時はインデックス再構築や LSM-tree的マージ が必要

ベンチマーク結果

  • データセット:10k, 100k, 1Mレコード でwrk負荷テスト
  • Go, Bun(JavaScript), Rust の3言語で実装・比較
  • Go追加検証 :ディスクバイナリサーチ&SQLite(純Go実装)
  • 主な結果(1Mレコード時のリクエスト/秒)
    • Go: 線形スキャン23、バイナリサーチ38,866、SQLite 25,085、メモリマップ97,829
    • Bun: 線形スキャン19、メモリマップ105,367
    • Rust: 線形スキャン152、メモリマップ169,106
  • 平均レイテンシ(1Mレコード時)
    • Go: 線形スキャン1,010ms、バイナリサーチ1.4ms、SQLite 2.1ms、メモリマップ584µs
    • Bun: 線形スキャン1,060ms、メモリマップ463µs
    • Rust: 線形スキャン753ms、メモリマップ221µs

考察と選択指針

  • 線形スキャンは規模とともに劣化、1M件で実用不可レベル
  • ディスクバイナリサーチは高速かつ安定、データ増加にも強い
  • SQLiteは常に安定したパフォーマンス、機能も豊富
  • メモリマップは最速・最小レイテンシ、ただしRAM依存
  • BunはGoよりメモリマップで高速、Rustは線形スキャンで圧倒的
  • 用途別最適解
    • 絶対速度:Rustメモリマップ
    • RAM非依存の高速:Goバイナリサーチ
    • SQLクエリ重視:SQLite
    • 最短開発:Go線形スキャン

25,000リクエスト/秒の意味

  • 25,000 req/s は大規模Webサービス級の負荷
  • ピーク時は平均の2倍程度(例:12,500 req/s平均ならピーク25,000 req/s)
  • 1ユーザーあたり1時間10回DBアクセス、ピーク同時接続10%想定
  • 例:10,000人SaaS利用でピーク3 req/s、100,000人アプリで30 req/s
  • 大半のアプリはベンチマーク値を大きく下回る負荷

データベースが本当に必要なケース

  • データ量がRAMに収まらない場合
    • メモリマップ方式は起動時全件ロードが必須
  • 複数フィールドでの検索やJOINが必要
    • ID以外の高速検索や複雑なクエリ
  • 複数プロセスからの同時書き込み
    • 外部一元管理が必須
  • エンティティ間のアトミックな書き込み
    • トランザクションやACID保証が必要

まとめ

  • 多くの初期・小規模アプリケーションではファイル管理で十分
  • 移行も容易(JSONLはどのDBにもインポート可)
  • 必要になった時だけデータベース導入 で問題なし
  • ベンチマークやサンプルコードも公開、実際に試せる環境提供

Hackerたちの意見

何億年も前に、Perlで小さな販売用ウェブアプリを作ったんだ。ISPのマシンに何もインストールできなかったから、ファイルバックハッシュを使ったんだよ。ユーザー用、注文用、他の何か用にそれぞれ一つずつね。年が経つにつれて、クライアントがもっと良いものに移行すると思ってたけど、結局20年近くそのままで、クライアントが亡くなった後、家族が引き継いで全部やり直した(今はWordPressで動いてる)。最後にチェックしたときは、何十万件もの注文があって、パフォーマンスも良かった。ハードウェアの進化のおかげで、このハックは予想以上にパフォーマンスを維持してたんだ。今ならSQLiteでも全然問題ないと思うよ。

どんな商品やサービスを売ってたの?

リレーショナルデータベースは恐竜じゃなくてサメだよ。 https://www.simplethread.com/relational-databases-arent-dino... 小さなアプリで得られるほんの少しのボーナスは、再開発にかける時間には全然見合わないよ。

サメと恐竜の対比は確かに適切なメタファーだね。白亜紀の頃、恐竜が全盛期だった時、サメはすでに今のサメにかなり似た形になってたんだ。例えば、今のホホジロザメやトラザメとほとんど変わらない大きなサメがいたりしてね。で、恐竜は翼竜やモササウルスと一緒に消えちゃったけど、サメはほとんど変わらず今まで生き残ってる。彼らはすでに最適化されたデザインに達していて、改善が難しかったからなんだよね。白亜紀の時代には、サメの他にも恐竜と一緒に存在していた2つの大きな捕食者グループ、ワニと今のニシキヘビに似た大きな締め付けヘビもいた。だから、サメ、ワニ、そして大きな締め付けヘビの3つは、70万年以上前に達成されたローカルオプティマムデザインの例なんだ。以降、大きなアップグレードは必要なかったんだよ。

自分でストレージを書くのは、データベースがどう機能するかを理解するのに良い方法だよ(効率的にやって、インデックスや正しいデータ構造を保つならね)。でも、もしただの遊びじゃなくて本気でやるつもりなら、最初からデータベースを使うべきだったって結論に至るはず。

この記事大好き!コンピュータがどれだけ速いかを示してるからね。ただ、一つ同意できない結論があるんだ。最後の方で、著者がフラットファイルでは対応できなくなるケースを挙げてるけど、「これらの制約は多くのアプリには当てはまらない」と言ってるんだよね。その制約の一つが「複数のプロセスが同時に書き込む必要がある」ってこと。実際、多くの初期段階のプロダクトは、別のワーカーで実行されるcronやメッセージキューを必要とするんだ。これらの複数のプロセスは、しばしば同時に書き込む必要がある。メインサーバーだけが書き込むように工夫することもできるけど、アーキテクチャが複雑になるんだよね。だから、純粋なスケールの観点からは著者に同意するけど、広い視点で見るとデータベースを使うのがベストだと思う。SQLiteはすごく理にかなった選択だし、スケールが必要なら、最も頻繁にアクセスされるデータをメモリにキャッシュすれば、両方の良いとこ取りができるよ。私のおすすめはSQLite + メモリキャッシュの組み合わせ。

Rustの1Mベンチマークを見たとき、どれだけ速いかを思い出させてくれる素晴らしい瞬間だった。

SQLiteは、DBが必要なプロジェクトを始めるときの新しい定番になったよ。パフォーマンスもすごく速いし、もし何かが成功してSQLiteを超えるようなことがあっても、Postgresに切り替えるのはそんなに難しくないと思う。別のデータベースサーバーを維持・バックアップ・管理する必要がないのは、安くて楽だしね。

これが結構気になるんだけど、あなたの言うことに実際に似てるのは、サーバーの冗長性が必要な時なんだよね。たとえ一つのサーバーで十分でも、どこかに運用しないとなると、ネットワークデータストレージが必要になって、ネットワークアクセス可能なデータベースの方向に進むことになるんだ。S3は時々うまくいくし、最近はファイルを原子的に取得できるようになったおかげで、いくつかの厄介な部分が改善されたけど、それでも唯一のストレージとしては不十分なことが多いよ。

原子的な操作が必要なら、データベースが必要だよ。ファイルシステムの上で原子的な書き込みをするのは、すごく脆弱だからね。これが多くのデータベースが永続性の問題を抱えていて、クラッシュ時にディスク上のデータが簡単に壊れる理由でもあるんだ。数年前のWindows上のRocksDBがその良い例だよ。開発中に定期的に壊れる問題があったからね。

正直なところ、今の時点でファイルに原子的な変更を加える必要があるデザインなら、SQLiteを使うようにデザインをやり直すかな。逆の発想はちょっとクレイジーに思える。「口から均一な高速度のミストでペイントを吐き出せるのに、スプレーペイントを使う理由は何?」もしその特異なスキルを持っているなら、ぜひ使ってみて。でも、持ってないなら、今から始める必要はないよね。それはちょっと甘い考えかもしれないけど、オペレーティングシステムのファイルシステムAPIを安全に使えるようになりたいな。それが自分をもっと良い人にしてくれると思う。でも正直、今の時代ではかなりニッチなスキルだと思うし、本当に今必要なのか、将来的に役立つのか考えた方がいいよね。それに、たとえ正しくやったとしても、あなたのコードを引き継ぐ人たちは同じスキルを身につけないだろうし、ボスに「変更するのは危険すぎる」って言うだろうから、結局データベースに置き換えられちゃうと思う。

いいね、もうACIDのAはカバーしてるね。それに、DuckDBみたいなOLAPデータベースがアウトオブコアのワークロードにどんなことができるかは、話し始めたら止まらないよ。

Hacker Newsで議論の続きを見る