インメモリテストデータベース
2005年11月22日
インメモリデータベースは、ディスクにアクセスすることなく、メインメモリ上で完全に動作するデータベースです。多くの場合、埋め込みデータベースとして動作します。プロセスが開始されると作成され、そのプロセス内に埋め込まれて実行され、プロセスが終了すると破棄されます。
多くの人はデータベースを大規模なディスク中心のものと考えていますが、そこには小規模ながらも活気のあるインメモリデータベースの世界が存在します。永続化する必要がない、または再構築できるような、ある種の管理されたデータへの高速アクセスを必要とするアプリケーションがあります(ルーターのルーティングテーブル、またはEventPosterを想像してください)。
しかし、従来のデータベースシステムの開発者でさえ、特にテストのためにインメモリデータベースが役立つことがあります。エンタープライズアプリケーションを開発する際には、データベースにアクセスするテストは、テストスイートを実行する際に大きな時間ロスとなる可能性があります。インメモリデータベースに切り替えることで、桁違いの効率化が実現し、ビルド時間を大幅に短縮できます。ThoughtWorkersの多くは、最近グリーンバーが表示されないと落ち着かないので、これは大きな違いを生みます。
テストのためにインメモリデータベースを利用する方法は、大きく2つのアプローチがあります。1つ目は、SQLインメモリデータベースライブラリを使用することです。Javaの世界では、HSQLDBが人気です。その他にはSQLiteやFirebirdなどがあります。これらのツールの良い点は、通常のSQLを使用してクエリを実行できることです。ただし、ターゲットデータベースと同じ方言を完全にサポートしていない、またはすべての機能を備えていない可能性があります。ファイルベースのデータベースをRAMディスク上で実行することで同様のことが実現でき、テストと本番環境のデプロイメントをより近づけることができます。
もう1つのアプローチは、すべてのデータベースアクセスをRepositoryの背後に抽象化することです。そうすることで、データベースを通常のインメモリデータ構造に置き換えることができます。多くの場合、オブジェクトグラフのエントリポイントへのハッシュテーブルの集合だけで十分です。リポジトリアプローチの長所の1つは、非SQLデータソースにも一貫性のある方法でアクセス(およびスタブ化)できることです。つまり、オブジェクトリレーショナルマッピングシステムもリポジトリ内に隠されます。
実際、SQLインメモリデータベースの使用を嫌う人もいます。それは、SQLまたはオブジェクトリレーショナルマッパーコードがドメインモデルに広がることを助長すると信じているからです。インメモリでSQLを実行すると、低速アクセスによる多くの問題は解消されますが、リポジトリの欠如を隠すための消臭剤のようなものになります。
これまでのところ、テストが主な推進力ですが、インメモリデータベースにはさらに可能性があると考えています。メモリのサイズが大きくなったため、多くのアプリケーションデータベースをメモリにロードできるようになりました。アプリケーションの状態へのすべての変更のイベントログを保持するアプローチを使用する場合、インメモリデータベースをログを適用した結果のキャッシュとして扱うことができ、必要に応じて再構築およびスナップショットを作成できます。このようなスタイルは非常にスケーラブルであり、多くのリーダーと少ないライターがいる場合に高いパフォーマンスを発揮します。私は、人々が非常に高性能なアプリケーションにインメモリデータベースを使用しているいくつかのケースに遭遇しました。ここでの違いは、これらの経験はニッチな商用データベースに偏っている傾向があるのに対し、テストではオープンソースを好む人が多いということです。
Prevaylerはこのようなアプローチを採用することで多くの注目を集めました。試したことがある人によると、インメモリオブジェクトへの緊密な結合とマイグレーションツールの不足が深刻な問題を引き起こしたとのことです。しかし、システムの記録としての永続的な変更ログのアプローチは、将来探求すべき肥沃な土壌であると考えています。
フォローアップ
このページを書いた後、興味深いメールをいくつか受け取ったため、いくつかの点を共有したいと思います。
ある通信者によると、SQLが得意だがオブジェクトが得意ではないタスクにインメモリデータベースを使用するのが好きとのことでした。SQLがオブジェクトや手続き型コードよりもエレガントに問題を解決できるケースは確かにありますが、通常はSQLで考えるのが好きな開発者は少数派です。
同僚のSteve Sparksは、最近のプロジェクトで、最初の呼び出し時にライブデータベースからデータを取得し、そのデータをファイルに保存してインメモリリポジトリを初期化することで、後続のクエリがデータベースにアクセスしないようにしたという話を聞きました。最初にC3プロジェクトでそれを見たのですが、SQLクエリ文字列をキーとしたハッシュテーブルにデータを保存していました。値が存在しない場合はDB2にアクセスし、結果をキャッシュしていました。
Steven Gravesは、私の最初のエントリではインメモリデータベースの一般的な用途について十分に説明していなかったと指摘してくれたため、書き直しを行い、タイトルも変更しました。
(Peter Becker、Zane Rockenbaugh、Steve Sparksのコメントに感謝します。また、内部メーリングリストに関する有益なコメントを提供してくれた多くのThoughtWorkersにも感謝します。