ネイティブ・オブジェクト・データベースを使うとき

Linuxユーザーは、質の良いリレーショナル・データベースに恵まれている。しかし、オブジェクト指向プログラミングに相応しいデータベース、リレーショナル・データベースではなく、db4oなどのオブジェクト指向データベースを使う方がよいことがある。

Linuxで使えるオープンソース・データベースは選り取り見取り。中規模以上のアプリケーションならMySQLやPostgreSQLが、小規模なアプリケーションや組み込みシステムであればHSQLDBなどのコンパクトなデータベースがある。いずれもリレーショナル・データベースで、それに見合った使い方――データの処理――をする限り、つまりデータベースのトランザクションを順次処理していくというデータ中心型アプリケーションである限り、大いに役だってくれる。

しかし、オブジェクト・ドメイン・モデルでアプリケーションを書いている場合、「データ」はオブジェクトに属し、オブジェクトにはシステムの挙動が含まれている。したがって、リレーショナル・データベースを使いつつオブジェクトに固執すれば、質の異なる不整合な2つのモデルを使ってデータを扱うことになる。

したがって、あくまでもドメイン・オブジェクトを貫くなら、リレーショナル・データベースを基礎づけているテーブル・パラダイムの中でオブジェクトを表す必要がある。どのようなテーブルがありデータの整合性と検索に必要なプライマリ・キーと外部キーの関係を定義するエンティティ・リレーション・モデルが必要となり、さらに、モデル間のマッピングを示す必要もある。たとえば、CustomerオブジェクトはCUSTOMERSテーブルに、CustomerオブジェクトのnameフィールドはCUSTOMERSテーブルのNAME列に格納されているなどということを表す必要がある。

こう書くと、それがどうしたと言われそうだ――みんなリレーショナル・データベースを使っているし、上で筆者が指摘したオブジェクト/リレーショナル・マッピング(O/RM)についても、そのための精妙のツールが用意されていると。しかし、どれほど優れたツールを使おうとも、この不整合は決して解消しない。大した問題ではないかもしれない――アプリケーションのクラスとデータベースのテーブルとが1対1に対応している限りは。

だが、実際には、重大な不整合が発生する可能性が高いのだ。オブジェクト・モデルとリレーショナル・モデルの挙動には際だった違いがあり、オブジェクトの扱い方が異なるからだ。大きな違いを幾つか挙げてみよう。

  • 識別:すべてのオブジェクトはフィールドの値によらない一意的な識別子を持っているが、リレーショナル・データベースのテーブルでは、一意性は、1つまたは複数の列に対するプライマリ・キー制約によって保証される。
  • 1対nの関係:オブジェクトの場合、所有関係は所有する側が保持し、1つのオブジェクトを所有することも、オブジェクトのコレクションを所有することもできる。たとえば、Customerオブジェクトは1つのAddressオブジェクトへの参照を1つ持ち、複数のAccountオブジェクトから成る1つのコレクションへの参照を1つ持つ。リレーショナル・モデルでは、このような関係性の保持は、関係性の種類ごとに、テーブル中の外部キー列を使って実装される。つまり、データ・モデルに外部キー列(これはオブジェクト・モデルでは不要)を含めなければならず、その関係性を辿るときはテーブルを結合しなければならない。
  • 有向性:オブジェクトの関係には向きがあり、参照の先にはそのオブジェクトが所有するオブジェクトがある。上の例で言うと、Customerの参照を辿ればAddressが得られるが、その逆にAddressオブジェクトからそれを所有するCustomerを探し出せるとは限らないということだ(それが必要なら、AddressオブジェクトにCustomer参照を保持させて、明示的に双方向的関係を設定しなければならない)。一方、リレーショナル・モデルの場合は、この向きが逆で、ADDRESSESテーブルの外部キー列によって関係性が保持される。その値がCUSTOMERSテーブルのキー列の値を指すのである。もっとも、これは大した違いではない。いずれにしても両テーブルを共通のフィールドで結合することになるからだ。これは、テーブル間の関係性の向きにはよらない。
  • n対nの関係:オブジェクト・モデルでは可能だが、リレーショナル・モデルでは直接これを表すことはできず、関係性を表すテーブルが必要になる。
  • 継承:オブジェクト・モデルでは、既存のクラス(新しいオブジェクトを生成する際のひな形)を基に、そのクラスの特別なケースとして新しいクラスを作り、基礎としたクラスの特性を継承しつつ新しい機能を追加することができる。しかし、標準的なリレーショナル・モデルには、この機能はない(PostgreSQLにはテーブルの継承機能がある)。しかも、継承による階層構造をテーブルにマップするための方法は幾つかあるが、最良の方法はないのだ。クラスとテーブルを1対1に対応させる方法、テーブルと具象クラスを1対1に対応させる方法、識別子フィールドで階層全体を1つのテーブルで表す方法などがあり、それぞれスーパークラスとサブクラスの持つフィールド値をフラットなテーブル構造に対応させる方法やデータの検索と階層の再構成の方法が異なり、パフォーマンス、ストレージ効率、維持管理のいずれかに弱点を抱えている。

ならば、どちらが「最良」のモデルなのだろうか。その答えは「どちらでもない」――それぞれに得手不得手があるのである。両者は本質的に異なるものであり、システムが複雑になるに従い、その違いが明瞭に現れてくる。初めはうまくいく。クラスは単純であり、O/RMは容易でマッピングに破綻はない。しかし、オブジェクト・モデルが複雑になるにつれ、マッピングも困難になる。

しまいには、開発のほとんどの時間をO/RMの作成に費やす事態になる。この「収穫逓減」――労力を投入するにつれ、得られる成果は少なくなっていく――現象は、Ted Newardがコンピュータ科学の泥沼と呼んだものである。

不整合を回避するには

こうした二律背反状態を回避する方法は2つある。オブジェクトを完全に捨ててしまうか(あるいは、ほとんど同じことだが、リレーショナル・データベースに容易にマッピングできるようなオブジェクト・モデルを設計する)、オブジェクトだけを使い、リレーショナル・データベースを全く使わないかのいずれかである。

それでは、オブジェクト指向プログラミングでは、どのようなデータベースを使うべきだろうか。もちろん、オブジェクト・データベースであることは明らかである。オブジェクト・データベースのスキーマはオブジェクト・データ・モデルに基づいており、アプリケーション・ドメイン・オブジェクト・モデルとほぼ平行関係にある。つまり、アプリケーション・オブジェクトのクラスとデータベースのクラスは、直接的な対応が可能なのだ。

オブジェクト・データベース――聞いた覚えがあるだろう。90年代に話題になり、やがてOracleなどの前に敢えなくも消えていった、あのオブジェクト・データベースである。あの頃のオブジェクト・データベースは、概して、複雑で高価だった。しかも、Object Data Management Group(ODMG)が提案した標準は、SQLなどのリレーショナル・データベースが広く受け入れられ馴染んだような成果を何一つ達成できなかった。

しかし、オブジェクト・データベースは戻ってきた。贅肉を落とし、体力をつけて。中には、オープンソースのものもある。現代のオブジェクト・データベースには、db4objects、GemStone、Objectivity、Progressの各社が提供するプロプライエタリ・アプリケーションだけでなく、OzoneやPerstなどの興味深いオープンソース・プロジェクトもある。db4objectsのdb4oプロジェクトなどは、両方の性質を持ち、MySQLとよく似たデュアル・ライセンス・モデルで提供されている。MySQLのように、GNU General Public License(GPL)でもプロプライエタリ・ライセンスでも利用可能だ。

これらのデータベースやそのほかのオブジェクト・データベースについては、最近開設されたODBMS.ORGポータルを参照されたい。オブジェクト・データベース関連の情報とリソースが豊富に揃っている。

オブジェクト・データベースの世界では、最近、オープンソースでもプロプライエタリでも、ネイティブ・オブジェクト・データベースが台頭している。オブジェクト指向アプリケーション向けに軽量でありながら強力なデータ保管・検索機能を提供することを目指しており、たとえば、モバイルや携帯型機器などで使うためのアプリケーション向けだが、有用性はそれだけに止まらない。

ネイティブ・オブジェクト・データベースであれば、アプリケーション・ドメイン・オブジェクトをほかの枠組み(オブジェクト・ベースのものであろうとなかろうと)にマッピングしたりバインドしたりする必要はない。アプリケーション・オブジェクトをそのままデータベースに保管するだけだ(JavaでもC#でも何でも)。1行のコードでオブジェクトを保管でき、関連オブジェクトのグラフ全体でさえ保管できるのだ。データベースのスキーマはドメイン・モデルを定義するクラスと全く同じものを使って定義し、照会はプログラミング言語自体で記述することができる。SQLを自分であるいはO/RMを使って書く必要はない。

パフォーマンス

オブジェクト・データベースなら、開発期間は短縮できそうだ。しかし、パフォーマンスが一定の水準に達していなければ検討対象には入れない。そこで、Pole Positionベンチマークの結果を見てみよう。ここには、db4oとさまざまなオープンソース・リレーショナル・データベース(O/RMツール使用、不使用)が比較されている。

結果を見ると、予想どおりの数字が並んでいる。アクセスするオブジェクトの構造が複雑であればオブジェクト・データベースが最良であり、リレーショナル・データベースに比して何倍というレベルで速い。O/RMツールの使用の有無にかかわらず、リレーショナル・データベースは全く歯が立たない。

一方、フラットで単純なデータであれば、パフォーマンスは、SQLの方が優れている。特に、オブジェクトごとに文字列を比較するような場合、高度に最適化されたリレーショナル・データベースはJavaや.Netが備えるネイティブ関数よりも遙かに優れている。db4oは高度な並列処理については最適化されておらず、大規模なマルチユーザー・データベース・アプリケーションでの利用は想定されていない。とはいえ、Webアプリケーションで活用されている事例が多々あるのは注目される。

おわりに

あらゆる開発者、あらゆるアプリケーションに使える万能のソリューションは存在しない。db4oのようなネイティブ・オブジェクト・データベースが得意とするのは、次の場合である。

  • ドメイン・オブジェクト・モデルを使って業務処理を実装すればROIが高くなると見込まれること
  • オブジェクト・モデルが、ある程度以上複雑であること
  • そのデータベースを使うアプリケーションは1本だけか、複数ある場合は、そのすべてが全く同じドメイン・モデルを持つこと

オブジェクト・データベースではデータとデータ・モデルの扱い方が通例とは異なるので、初めは戸惑うだろうが、それによって得られるものの大きさに驚くに違いない。

Jim Patersonは、グラスゴー・カレドニアン大学(英国)コンピューティングと数学学部講師。専門はオブジェクト指向ソフトウェアとWeb開発。特に、教育場面での新しいツールの使用に関心を持つ。物理学博士号(グラスゴー大学)。現職の前は、リサーチ・フィジシスト、ソフトウェア・エンジニア。著書、「The Definitive Guide to db4o」(発行Apress)。

NewsForge.com 原文