メインコンテンツまでスキップ

RDBとスキーマレスDBの使い分けについて

Sato Taichi

はじめに#

RDB とスキーマレス DB をどういう基準で使い分けるのかを、会社で聞かれた際に答えた雑な回答をメモ書きしておく。

他にも多くの基準があるだろうし、スキーマレス DB というか KVS は様々な実装があり、そのそれぞれが微妙に違うので議論として曖昧な部分はある。

特に、運用面やデータ量がペタバイトクラスになる状況については考慮していない。

僕は SI 戦士なので、最終的には金を無限に突っ込んだ Oracle 先生が最高のデータベースであると考えている。

そういうバイアスのある人間の意見だと思って以下の文章は読んで欲しい。

念頭に置いているデータベースについて#

このエントリを書くにあたって念頭においているデータベースは以下の通り

最初は Redis を DB と書いていたけども、僕の認識違いが明らかになったので DB でない方に移した。

念頭に置いていないデータベースについて#

このエントリを書くにあたって念頭においていないデータベースのようなものは以下の通り

これらをデータベースだと言う人もいるだろうが、僕はこれらをデータベースとは考えていない。

意見の相違がある方はアンサーエントリを書いて頂けると勉強になるのでありがたい。

スキーマを事前定義するか?#

一番大きな違いは、スキーマを事前定義するのか、事後定義つまり、格納されているデータがスキーマなのである、というアプローチをとるのかが違う。

スキーマを事前定義するためには、ストレージされるデータの構造を厳密に規定しなければアプリケーションを作り始められない。

一方で、スキーマを定義しないのであれば、手に入れたデータを JSON か何かにシリアライズすれば、とりあえず DB に格納できる。

つまり、これから作ろうとするアプリケーションをどれだけ厳密に設計したいか?というのが、最初の使い分け基準になる。

トランザクションを使いたいか?#

次にトランザクションモデルが違う。

RDB では、トランザクションを使えるので複数のデータを追加したり更新する時の整合性を取るのが非常に簡単だ。データの整合性を保障するのはデータベースの役割となる。

一方で、スキーマレスな DB の殆どはまともなトランザクションをサポートしていないので、複数のデータを追加したり更新する時の整合性を取るのはアプリケーションコード側でやらなければいけない。

トランザクションモデルの違いは、DB に格納するデータ構造の違いにも表れる。

RDB では、ユーザや、部署、会社のようないわゆるマスタデータは、それぞれ正規化して独立したテーブルにするのが望ましいとされる。これは、ユーザと部署と、その連関テーブルを同時に更新するのが容易いからだといえる。

一方で、スキーマレスな DB では、一つのビジネストランザクション内で必要なデータは一つの塊として保存してしまうのがよい。

データは正規化されている訳では無いので、複数のビジネストランザクション間で、同じ筈のデータが同じでなくなってしまう可能性はある。それが問題になるようなアプリケーションではスキーマレス DB を使わなければいい。

これから作るアプリケーションにおいてトランザクションは必要か?必要ない場合に、データが非正規なままでも問題が置き辛いようなアプリケーションか?が二番目の使い分け基準になる。

高度なクエリ言語を使いたいか?#

3 つ目の使い分け基準の話は、DB の実装によって違うのでおおまかな話になるが、クエリの複雑さの話だ。

RDB では標準化された極めて高水準で高機能な SQL を使える。集合論に基づいて設計された SQL は DB というデータの集合を操作するために最適化された構造をしている。

一方で、多くのスキーマレス DB には、それ程高水準なクエリ言語は搭載されていない。

ちょっと日付で範囲クエリが使えるだけで優位性があるとみなされるレベルだ。

多くの場合は、KVS 等と言われるように、DB に格納されているモデルの特定のフィールド、つまりキーを基準に 1:1 でデータを取出せるだけだ。集合に対する操作が必要なら、アプリケーションコードの中で、map だの reduce だのと言った関数を駆使することになる。

データの量が十分に少なければ、アプリケーションコードで集合を操作すること自体が問題になることはないだろう。

一方で、データの量が大きい場合、つまりメモリに乗り切らない程度に大きくなる場合、アプリケーションコードとして適正に動作する集合操作のコードを書くのは飛躍的に難しくなる。一度に操作しきれないので、部分的にファイルに書きだしたり、DB からデータを少しずつ取り出しながらソートしたりといったコードを書くのは、恐ろしく難しいので出来れば避けるべきだ。

更にデータ量が大きい場合、つまりデータベースを分散化せざるをえない程度に大きくなる場合には、さらに別な手段を考える必要がある。これは、ビッグデータ界隈の話になるので、そちらについては言及しない。

まとめ#

以上をまとめると、RDB とスキーマレス DB の使い分けの基準は3つ

  • スキーマを事前定義するか?
  • トランザクションを使いたいか?使わない場合、それに伴うデータモデルのあり方を許容できるか?
  • 高度なクエリ言語を使いたいか?