こまどブログ

技術のこととか仕事のこととか。

『データ指向アプリケーションデザイン』を読む(3):2章「データモデルとクエリ言語」

『データ指向アプリケーションデザイン』の2章「データモデルとクエリ言語」についての読書メモ。

データ指向アプリケーションデザイン ―信頼性、拡張性、保守性の高い分散システム設計の原理

データ指向アプリケーションデザイン ―信頼性、拡張性、保守性の高い分散システム設計の原理

データモデルと抽象化

前章に続いて、抽象化というキーワードが出てくる。

それぞれのレイヤーはクリーンなデータモデルを提供することによって下位のレイヤーの複雑さを隠蔽してくれています。こうした抽象化によって、たとえばデータベースベンダーのエンジニアや、そのデータベースを使うアプリケーション開発者など、様々なグループの人々が効率的に共同で作業できるのです。*1

各言語(自分が念頭に置いているのはJavaだが)コレクションを取り扱うライブラリや、それを更に隠蔽したファーストクラスコレクションは、下位レイヤーの隠蔽のわかりやすい例だと言えるのではないか。インピーダンスミスマッチはこの文脈では言及されていないが、隠蔽が極めて複雑な仕方で行わなくてはならない異なるデータモデル同士の関係を言うものと理解できると思う。

ドキュメントモデル

ドキュメント型のデータモデルについて、紙幅を割いてその特徴を論じている。本文中では、ドキュメント型木構造が明示されている(それゆえ、個人の履歴書のような構造のデータには親和的である)ことや*2、ドキュメントデータベースの多くで結合のサポートが弱いこと*3が指摘されている。しかし、この書籍の特徴的な態度でもあるが、異質なものと理解されている複数のものをわかりやすく対比させるだけでは終わらずに、共通性や中間的なあり方についても言及している。たとえば、多対一や多対多の関係の表現において、リレーショナルデータベースでもドキュメントデータベースでも識別子による参照(外部キー、ドキュメント参照)が行われるという指摘などである*4

アプリケーションにおけるドキュメントモデルの利用については、以下のような原則を示しながらも、別の箇所では、「仮にアプリケーションの初期バージョンが結合が不要なドキュメントモデルにうまく適合したとしても、アプリケーションに機能が追加されていくにつれて、データ同士はつながりを持つようになるものです。」*5と指摘している。ドキュメント型に適合している例として挙げられた履歴書の情報が、どのようにドキュメント型の枠を超えてくるかという説明もわかりやすい。

アプリケーションのデータがドキュメントのような構造を持っている(すなわち一対多の関係からなるツリー構造を持ち、通常はそのツリー全体が一度にロードされる)なら、おそらくはドキュメントモデルを利用するのは良い考えです。リレーショナルな手法である細分化(shredding)、すなわちドキュメントのような構造を複数のテーブルに分割することによって、スキーマが込み入ったものになり、アプリケーションのコードが不必要に複雑になることがあります。*6

ドキュメントモデルの特徴であるローカリティについては以下のような指摘もなされている。大きなデータを一箇所にまとめておくことで一度に全体を取れるというメリットが、ドキュメントのサイズを大きくすること自体によるデメリットゆえに実際に享受しにくくなっているというのは面白い現象で、同種の事態はデータモデル以外の文脈でも見られるのではないだろうか。設計を考える際には頭の隅に置いておきたい。

ローカリティのメリットが生じるのは、一度のドキュメントの大部分が必要になる場合に限られます。通常、ドキュメントの一部にしかアクセスしない場合でも、データベースはドキュメント全体をロードしなければならず、これはドキュメントが大きければかなり無駄になるかもしれません。ドキュメントを更新する場合には、通常ドキュメント全体を書き直さなければなりません。変更の処理をその場所でデータを上書きして済ませられるのは、エンコード後のドキュメントのサイズが変わらない場合だけです。そのため、概してドキュメントは小さく保ち、ドキュメントのサイズを大きくするような書き込みは避けることが望ましいです。こうしたパフォーマンスの制約があるため、ドキュメントデータベースが有効になる状況はかなり減ってしまいます。*7

クエリ言語とグラフ型データモデル

様々なクエリ言語を紹介しながら、それぞれの特徴を記載している。大きく取り上げられているのは、宣言的言語、APIの魅力である。並列処理への適合性という文脈で宣言型を語るのはJavaにおけるforループとStream APIの違いなどと同じだ。また、書籍中ではスタイルの適用におけるCSSJavaScriptの違いも宣言型/命令型という文脈で捉えられている。具体的な例を挙げて両者の違いが影響を及ぼす理屈を説明していてわかりやすい。

宣言的な言語が魅力的なのは、通常それが命令型のAPIに比べて簡潔で、扱いやすいためです。しかしもっと重要なのは、それがデータベースエンジンの実装の詳細も隠蔽してくれることであり、そのおかげでクエリの書き換えなしにデータベースシステムはパフォーマンスを改善できるのです。(中略)最後に、宣言型の言語は並列実行に向いていることがよくあります。今日では、CPUの高速化はクロックを高速にするのではなく、コア数を増やすことによって達成されています。*8

クエリ言語と併せて細かく論じられているのはグラフ型のデータモデルについてだ。多対多のデータの関連が支配的になってきた場合には、ドキュメント型やリレーション型ではなくグラフ型のデータモデルが親和的になる。グラフ型のデータモデルには個人的に馴染みがなく、CypherやSPARQLといった、書籍中で紹介されているクエリ言語も知らないものばかりだった。SQLにおける再帰共通テーブル式WITH RECURSIVE)もグラフ型データモデルの文脈に位置付けられている。

これまでに、多対多の関係が様々なデータモデルの重要な機能の差異になっていることを見ました。アプリケーションの持つ関係のほとんどが一対多(ツリー構造)だったり、レコード同士が関係を持ったりしないのであれば、ドキュメントモデルが適しています。しかし、データ中で多対多の関係が一般的だった場合はどうでしょうか?リレーションモデルは多対多の単純なケースは扱えますが、データ同士の繋がりが複雑になっていくと、データをグラフとしてモデル化するほうが自然になっていきます。*9

上の一節では、関連の観点からドキュメント→リレーショナル→グラフという展開が示されている。のちの部分では、階層型の欠点を補うものだったリレーショナルモデルのあとに、「NoSQL」という括り方をされるものの方向性を異にする二つのものとして、関係の取り扱いを重視しないドキュメントモデルと、複雑な関係を取り扱うのに適したグラフモデルが登場したという歴史的な展開が示されている*10

スキーマレス」を巡って

データモデルを語る際にしばしば使われる「スキーマレス」の概念についても、わかりやすい説明がなされていた。以下の一節では、ドキュメントデータベースにおける「スキーマレス」(=スキーマオンリード)と、リレーショナルモデルにおけるスキーマオンライトとの対立を、プログラミング言語における動的型付けと静的型付けとの対立と類比させている。言われてみるとなるほどと思わされる説明である。

ドキュメントデータベースはしばしばスキーマレスだと言われますが、これは誤解を招く表現です。なぜなら通常、データを読み取るコードは何らかの構造があることを前提とするからです。もっと正確な言葉を使うなら、これはスキーマオンリード(データ構造は暗黙のものであり、データの読み取り時にのみ解釈される)であり、スキーマオンライト(リレーショナルデータベースにおける伝統的なアプローチであり、スキーマは明示され、データベースは書き込まれるすべてのデータがそのスキーマに従っていることを保証する)の逆です。スキーマオンリードは、プログラミング言語における動的(実行時の)型チェックに似ており、一方でスキーマオンライトは静的(コンパイル時の)型チェックに似ています。*11

感想

抽象化や宣言型、それに最後のスキーマと型付けの話など、この書籍では、アプリケーションのプログラミングの領域で馴染みのある物事の捉え方が、データモデルやクエリの領域にもうまく適用されているような印象を持つ。これまで主にアプリケーションの内部の設計やコードの記述方法について勉強する中で身につけてきた考え方が他の領域にも活かせる、ということを感じさせてくれ、勇気付けられる。抽象的になりすぎずに具体的な事例を交えつつこのような議論ができるというのは、経験と思考が高度に組み合わさっていてこそだと思われ、著者に対しては畏敬の念を禁じ得ない。

*1:30ページ。

*2:33ページ。

*3:36ページ。

*4:40ページ。

*5:36ページ。

*6:41ページ。

*7:44ページ。

*8:46ページ。

*9:51ページ。

*10:65ページ。

*11:42ページ。