クラウド上のデータベースとして、分散型のキーバリューストア(分散KVS)を用いることが多くなった。分散KVSは、スケーラビリティーに優れており、特にユーザー数が多いシステムでは利用価値が高い。

 ただし、分散KVSにはいくつかの制約があり、システム開発に利用する際には、これまでの“RDBMS脳”をいったんリセットする必要がある。中でも、RDBMSでは真っ先に考慮していた「正規化」については、分散KVSでは原則として行ってはいけない。

分散KVSの四つの特徴

 なぜ分散KVSでは正規化をしてはいけないのか。これを理解するには分散KVSの特徴を押さえる必要がある。分散KVSには、大きく四つの特徴がある(図1)。

図1●分散KVSの四つの特徴
図1●分散KVSの四つの特徴
[画像のクリックで拡大表示]

 一つは、分散KVSでは問い合わせにキーを使って、バリュー(値)を取得することだ。データ構造が単純なので、データの取り出し時間が短くて済む。PerlやPHPの連想配列や、JavaのMap、C#のHashtableに相当するものだ。ただしキーを厳密に指定する必要があり、あいまい検索や部分一致による検索はできない。

 二つ目の特徴は、RDBMSのような「スキーマ」が分散KVSには存在しないことである。RDBMSではスキーマをRDBMS側で管理し、アプリケーションはSQL文をRDBMSに渡すことで必要なデータを取り出せた。これに対してスキーマがない分散KVSにはどんな値も格納できる。その半面、SQL文で容易に実現できたジョインや範囲検索は、アプリケーション側で実装する必要がある。

 分散KVSでは複数のノードでキーとバリューの“ペア”を管理している。このためどのノードにどのキーとバリューが置かれているか分からない。これが三つ目の特徴だ。データによって、格納されているノードが違うので、データアクセス時間にバラツキが出やすい。また、データ変更には一定の時間がかかり、ダーティリード(データ更新中にそのデータを読み出すこと)が発生する可能性もある。

 四つ目は、分散KVSではノードを追加することで性能やデータ保持サイズを増やせることだ。実装に依存することだが、一般に分散KVSではノード追加が見込まれており、スケールさせるのは容易である。

アプリ側の作り込みが大変に

 こうした特徴を踏まえると、なぜ正規化してはいけないのかが見えてくる。正規化は、データの一貫性を目的とした作業である。データモデルの中にある“繰り返し”を排除し、主キーによって従属関係を設定する。同じデータがあちこちにないように、テーブルを分割していく作業である。

 スキーマが存在するRDBMSは、正規化をほぼ機械的に実施できた。正規化することで、データベース中に分散する同一データの重複が排除され、アクセスするデータ量やI/O時間が減り、結果として性能が向上する。

 これに対して分散KVSでは、バリューに何を入れてもよいが、それを解析するのはアプリケーション側である。データを正規化するということはテーブルを分割するということなので、ジョインなどが備わっていなければ、データを取り出して統合・加工する処理をアプリケーション側に実装しなければならない(図2)。この負担は小さくない。

図2●分散KVSにおいて正規化したデータを取得する流れ
図2●分散KVSにおいて正規化したデータを取得する流れ

 加えて、分散KVSではすべてが一つのノードに置かれていたRDBMSとは異なり、どのノードからデータを取り出すのか分からない。このため一つのテーブルを正規化して三つに分割した場合、三つのノードにアクセスしてデータを取得する可能性が高い。データ取得にかかる時間は、単純に見て正規化しない場合の3倍だ。ノードが物理的に近くに存在すればよいが、クラウド上では拠点をまたいでデータを取得するケースがある。この場合、取得時間は3倍どころではなくなる。

 もっとも、分散KVSでも正規化するメリットがないわけではない。例えば、正規化すれば重複するデータがあちこちに存在する状態を防ぎ、データの一貫性を保てる。また、重複するデータを減らすことによって、保管領域を少なくできるメリットがある。

 このように、分散KVSでは正規化することのデメリットとメリットがある。それでも多くの場合は、分散KVSで正規化すると、メリットよりもデメリットの方が大きくなりやすい。場合によっては、分散KVSではなく、RDBMSを使った方がよいというケースもある。これらの点に注意して、分散KVSのデータベース設計に臨む必要がある。

 RDBMSのような「とにかく正規化をすべき」という考え方は取り払い、アプリケーションの特性に応じた正規化を考えなければいけない。

大川 博(おおかわ ひろし)
日本ヒューレット・パッカード エンタープライズサービス事業統括アプリケーションサービス統括本部 アプリケーションデベロップメント本部 運輸アプリケーションデベロップメント部
2001年、コンパック(現日本ヒューレット・パッカード)に入社。通信・製造・金融などさまざまな業種のユーザー企業のJ2EEやWebのシステムを担当した後、2004年からは運輸のユーザー企業を担当する。以降、主に.NETでのシステムに携わっている。社内ではマイクロソフト関連技術についての技術展開にも積極的に実施している。