はじめに
データモデリングには主観的な側面があります。実際、その数学的な基礎にもかかわらず、データモデリングのほとんどの側面は主観的だと言っても過言ではありません。情報をどのように表現するかという問いには多くの答えがあり、文脈に最も適したものが常に明確であるとは限りません。実装の詳細に入る前に、その文脈と要件を可能な限り理解しようと努めるべきです。これには時間と他者の時間、そして多くの質問が必要です。調査とインタビューは、データベース設計において、ユーザーエクスペリエンス設計と同じくらい重要です。不完全すぎる、詳細すぎる、侵害的な、あるいは構造の悪いデータは、システム保守者だけでなく、ユーザーや対象者にとっても少なくとも同じくらい苦痛を与える可能性があります。たとえ要件を手渡され、実行を命じられたとしても、問題とその起こりうる結果を最後まで考え抜くのは、おそらくあなたが最初の人でしょう。
データモデリングの問題の核心は、有用なエンティティを定義し、それらが接続のウェブまたはグラフ内で相互にどのように関連するか、また関連するかどうかを特定することです。これらのエンティティは、物理的なオブジェクトのクラスや抽象的な概念、そしてその中間にある、場所、出荷、割り当てなどの多数のものを表します。しかし、この記号空間を占める表現は物理法則に縛られず、記号表現と被記号との間に厳密な1対1の対応があるとは限りません。単一のエンティティが、作業中の多くの概念に共通する側面、あるいはシステム全体を表すこともあります。あるいは、単一の概念に見えるものが、多くの部分に分割することでより有用になったり、管理しやすくなったりすることもあります。
どんなエンティティもそれ自体ではそれほどの意味しかありません。ズールー族のことわざ「人は他者を通して人となる」は、抽象的な表現においても真実です。データモデルが孤立した事実の単一のカテゴリを表すことはめったになく、より多くの場合、システムを表しており、いくつかのコンポーネント間の関係や相互作用は、システムを正確かつ有用に表現するために、コンポーネント自体と同じくらい重要です。
主観性があるため、これらの質問を抽象的に答えることは不可能です。これは、思考を深めるための練習であり、収集するデータに関心を持つ人々に積極的に質問することで調査するべきものです。たとえそうであっても、最初に導き出した答えはせいぜい暫定的なものでしょう。リリースまで変更されずに残るデータモデルは稀です。
エンティティとして適格なほど重要なものは何か?
「本当に重要なカテゴリは何だろう?」という問いは、あまりにも明白すぎて、仮定を固めようとするときですら見過ごされがちです。どのようなデータベースを使うにしても、システムの主語と目的語を定義することが最初に考えるべきことです。これはデータストアの選択にも関係します。たとえば、大量の計測値や、更新よりも読み取りがはるかに多い単純な事実を重視するのであれば、CassandraやHBaseのようなカラムナーデータベースを選ぶべきでしょう。
リレーショナルデータベースは「複雑な(complicated)」ものです。システムについて語るとき、「複雑な(complicated)」は「複合的な(complex)」と区別されるべきです。複合的なシステムには、ニューラルネットワーク、経済、言語、生命そのものが含まれます。各コンポーネントは限られた文脈情報に基づいて他の多くのコンポーネントと相互作用し、システム全体がその環境と相互作用し、履歴と振る舞いが現れます。
一方、「複雑な(complicated)」システムは、多くの個々の部分で構成されており、それぞれが時計やエンジンのリズムで作用し、作用を受けています。データベースに履歴をエンコードしたり、振る舞いを定義したりすることは可能ですが、それは厳密にトップダウンの作業です。データモデルにおける一見して出現的な特性は、決定論的なバグでしかありません。データモデルの要素は他の要素と相互作用しますが、常に同じ方法で同じ他の要素と相互作用します。そして、一部の要素は、データベースでの表現において、潜水艦にとっての網戸のようなものであり、せいぜい機械的故障の追加点となるだけです。
エンティティ間のどの接続が重要か?
複数のユーザーベースとそのデータが同じテーブルに格納されるデータモデルを設計する方法は2つあります。マルチテナンシーというより広範な問題については後で触れますが、共有スキーマモデルには、モデリングにおけるいくつかの主要な懸念事項を示す特定の選択肢があります。それは、すべてのレコードにtenant_id
値を含めるべきか、それともテナントに直接的で意味のある接続を持つレコードのみを含めるべきかということです。
概念的には、外部キー制約が強制されている限り、行がどのテナントに属するかを特定するのはそれほど難しくありません。テーブルからテーブルへ、関係をたどってtenants
へとJOIN
していけば、探しているtenant_id
値を含む結合結果がそのテナントに属することになります。ただし、スキーマがさらに進化するとSQLの管理がかなり面倒になる可能性があり、システム内のデータが十分な量になるとパフォーマンスが懸念され始めることがあります。だからといって、遠いテーブルで追加のtenant_id
列を管理することが自動的に価値があるわけではありませんが、それが妥当な決定になるために多くのことは必要ありません。
エンティティとリレーションシップは、ノードとエッジの有向グラフを構成します。ここでの「有向」とは、エッジが一方向の接続であることを意味します。tenant_id
値を持つレコードは、tenants
テーブルの存在とその中の特定のレコード(適切な外部キー制約が設定されていれば、示唆するだけでなく保証します!)の両方を示唆します。しかし、tenants
からのレコード自体は、他のどのようなデータがそれに属するかについては何も示唆しません。
ノードやエッジが追加されるたびにグラフは複雑になり、データモデルの維持と改善にはさらなる労力が必要となります。しかし、この複雑さはグローバルな問題であると同時にローカルな問題でもあります。エンティティの集合は、管理と使用の両方において困難な、十分に重要な関係の絡み合いで接続されることがあります。これらのサブシステムは、PostgreSQLのようにビューやテーブル継承などのメカニズムによってある程度隠蔽されることが多く、オブジェクト指向ソフトウェア開発におけるファサードパターンと似たような効果をもたらします。
組織単位はどのように相互作用するか?
あなたのモデルのあらゆる要素 — それがエンティティであろうと、リレーションシップであろうと、複数のエンティティとリレーションシップから構成されるサブグラフであろうと — は、あなたが設計している組織の一部、またはそのような単位間の相互作用の焦点を表す可能性があります。在庫は製造とロジスティクスを、またはロジスティクスと販売を結びつけます。経費記録は財務と人事、そして人事を会社全体の各部門と結びつけます。一部の主体は、ごく少数のエッジにあるエンティティを介して主にモデルと相互作用するかもしれません。これは、システムのより深い動作に関する洞察が少ない場合に課題となる可能性がありますが、より多くの可視性と他の部門との接触を与えることで、組織全体の機能改善の機会となることもあります。
Conwayの法則(Conway's Law)ほどに定着した観察はほとんどありません。組織はシステム設計において、そのコミュニケーション構造を再現せざるを得ず、データベースも例外ではありません。データモデリングの問題の中には、全体または部分的に、データベースではほとんど助けにならないコミュニケーションの問題であるものも存在します。
どの程度の詳細さか?
最初の2つの質問を逆にして考えてみるのも有用です。もしこの可能性のあるエンティティやその関係を完全に無視したら、データモデルのユーザーは何を失うだろうか?もちろん、最初に重要だと特定した要素のほとんどは、実際に重要です。しかし、中には一見したほど重要ではないものもあり、それらを省略したり簡素化したりすることで、モデル全体の機能と保守性を向上させることができます。
重要性という問いには、「はい」と「いいえ」以上の答えがあります。問題領域の特定の側面をそれ自体がエンティティとして表現する必要はないかもしれませんが、存在や数量など、より一般的で管理しやすい事実には依然として関心があるかもしれません。製造業では、部品番号は、校正、プロセス履歴、サブコンポーネント、容量、許容範囲など、さまざまな特性が異なる部品タイプにとって重要となる豊富な情報への鍵となります。倉庫業では、部品番号はSKU(「在庫管理単位」から)となり、重要な詳細ははるかに単純になります。つまり、いくつあるか、何色か、どれくらいの重さか、そしてどこにあるか、といったことです。
一部の情報は有用ですが、すでに独自の内部構造を持っており、それをエンティティやリレーションシップに変換するのはあまり便利ではありません。階層、ハイパーテキスト文書、部品表、さらにはデータベース内の他の場所にあるエンティティリレーションシップのサブグラフの一時的な「作業コピー」などです。これら、またはそれらが含む情報は、リレーショナルに表現できますが、外部構造と内部構造の境界を越える重要なリレーションシップがない限り、それらを分解する労力に見合う価値はおそらくありません。もしこの種の情報があなたの主な関心事であれば、(階層的なドキュメント向けに)CouchDBやMongoDBのような専門的なデータベースが適切かもしれません。もしそれらが他のリレーショナルモデルの例外であれば、JSONやXMLのようなデータ型が、モデルを2つ以上のデータベースに分割するのを避けるのに役立ちます。追加のデータストアが増えるたびに維持と調整の作業が増えるだけでなく、リレーションシップが前提とする情報が消滅しないという保証である参照整合性は、単一のデータベース内でしか保持されません。
どのようなサブグラフ、集計、統計が有用か?
リレーショナルデータベースのクエリには時間がかかります。具体的にどれくらいの時間がかかるかは、ディスク速度やCPUパワーといったホストコンピューターの物理的特性、キャッシングや最適化といったRDBMSの操作能力、そして最後にクエリ自体の構成など、さまざまな要因によって異なります。データモデルは、最初の2つのクラスによって設定される制限に対応する必要がありますが、その成功を決定する主な要因の1つは、3番目の問題であるクエリの構成の問題をどれだけうまく予測できるかです。
関係の範囲の数は、パフォーマンスと保守性の両方において、クエリ構成の最も重要な側面の一つです。高いJOIN
カウントは、特に結合されるエンティティが小さいか、適切にインデックスされている場合、必ずしも許容できないパフォーマンスを意味するわけではありませんが、最良の場合でも、それぞれがクエリ作成者の認知的負担を増大させます。あなた自身、バックエンド開発者、およびその他のデータベースユーザーが、一般的に必要とされる結果セットを組み立てるのが可能な限り簡単であるべきです。
データベースには、これを達成するためのいくつかのツールが用意されています。ビューは、頻繁に使用されるサブグラフとそれらに対する計算をカプセル化し、ユーザーやアプリケーションから複雑さを隠蔽するのに役立ちます。データベースで二次表現を一元化することで、例えば、すべての付随情報を含む発注書や、倉庫の一般的な統計の単一の正規表現が保証されます。通常のビューは、実行中のステートメントに統合される保存されたクエリであるため、パフォーマンスには寄与しません。しかし、ほとんどのリレーショナルデータベースは「マテリアライズドビュー」(MySQLとMariaDBが顕著な例外)をサポートしています。これらはデータをテーブルのようにディスクに永続化するため、取得がはるかに高速になりますが、そのデータは古くなり、更新が必要になります。
ここでの最後の手段は非正規化です。エンティティのデータや、カウントや合計などの有用な集計を、別のエンティティのプロパティとしてインラインで格納することです。正規形については今後の章でさらに深く掘り下げますが、これは軽く考えてはいけないステップだと言っておきましょう。それでも、必要なデータを組み立てるのに法外な時間がかかるのであれば、より高い正規化レベルを放棄することは、追加の管理努力に見合う価値があるかもしれません。ここで極端な手段を講じる必要がある場合は、もう一度カラムナーデータベースについて考える時期です。
保存すべきでないものは何か?
持っていない情報について責任を負う必要はありません。データを保護するための産業全体が存在しますが、いかなるセキュリティ対策も完璧ではありません。非常に厄介な問題を避ける最も簡単な方法は、そのような問題を引き起こす可能性のあるデータを収集しないことです。ただし、これはデータベースに限らず、ログ、レポート、ソース管理、その他のシステムにも機密情報が現れる可能性があることに注意してください。
最も大きな影響を及ぼし、他を寄せ付けないほどの機密性の高い情報とは、人間に関するものです。人間に関する情報は必然的に政治的であり、人間が参加するシステムのモデリングは、モデラーの政治を反映し、強化します。誰が、どのような資格で、どのような特性が重要または重要でないと仮定され、誰に見える形でシステムに入力されるか:そのすべてが政治です。個人データの軽率または侵略的な扱いの影響は、まだ始まったばかりです。ますます多くの人々の情報がデータモデルに継続的に流れ込んでおり、これらのモデルは多くの場合、適切な注意を払って開発されていません。数多くのケースで、それらの情報は、その情報を悪用するために明示的に設計されてきました。
個人識別情報(PII)は、他のデータが誰に関連するかを示します。PIIがなければ、ランダムな医療記録は真空中の履歴です。どこかの誰かが、番号だけで知られている誰かが、これらの小児期の予防接種を受け、肺炎にかかり、小さな皮膚がんを患い、ある時点で薬物依存症になり、インフルエンザに数回かかり、双極性障害を患っていたとします。その医療記録番号を氏名と住所に紐付ければ、突然あなた――あるいはそれを見ることができる誰でも――特定の人物の人生について、彼らが意図しない、あるいは他人に知られたくない多くのことを知ることになります。私たちがうまく保護できないデータを収集することの結果は、そのデータを持つ人々にとって、短い不快な会話から、失業、個人情報窃盗、恐喝、さまざまなヘイトクライムに至るまで多岐にわたります。
医療記録に関しては、多くの国でアクセスと開示を管理する厳格な法律があり、それは正当な理由によるものです。ほとんどの他の文脈での情報は、もしあるとしても、それほど厳格な法的管理下にはありません。それは、名前や住所、生年月日、生体認証、母親の旧姓、パスポートや納税者番号のような政府発行の身分証明書の値などを、どの程度厳重に保護する必要があるかをあなた自身が判断する責任があることを意味します。PIIは予期しない場所にも現れることがあります。2004年にAOLが匿名化したと思っていた検索ログを公開した際にそれが起こりました。さらに悪いことに、識別できない事実でも十分な量があれば識別可能になります。あなたと同じ居住都市、性別、役職、携帯電話のモデル、お気に入りのレストランを持つ人が他に何人いるでしょうか?その事実の組み合わせと関連付けられる可能性のある他のものは何でしょうか?
別の種類の機密情報として、他人の代理で行動できるものがあります。ソーシャルメディアやその他のウェブ認証情報、銀行のルーティング情報や口座情報、クレジットカード番号はすべて、信頼に基づいてあなたに与えられます。場合によっては、特に支払いに関する取引では、あなたからこの信頼の負担を取り除く第三者サービスが存在します。特別な理由がない限り、それらを使用してください。
次に何が起こるか?
データモデルは静的ではありません。要件は進化し、ビジネスは転換し、外部の情報源は現れ、変化し、消滅します。これはアプリケーション開発の活発なペースと同じ速さで起こるわけではありませんが、大きな変更から小さな調整まで、あらゆる中間的な変化が確かに起こります。慎重な設計は、よりゆっくりで小さな変更にバランスを保つのに役立ちますが、ある時点でデータモデルに大規模な修正が必要になるという保証は決してなく、一見小さな変更でさえ、デプロイ時に予期せぬ困難を引き起こす可能性があります。例えば、PostgreSQL 11までは、非NULLのデフォルト値を持つ新しい列を追加するには、テーブル内のすべてのレコードを書き換える必要がありました。これは数百万行にも及ぶ場合、あまり楽しい作業ではありません!
現在は未来よりも重要です。もしあなたのモデルが今有用でないなら、それが後で有用になる機会はおそらく訪れないでしょう。しかし、自然または不自然な選択の力が常に働いており、これらの圧力に適応できないデータベースは消滅します。将来の可能性への計画については後で詳しく説明しますが、行き詰まる角があることを知っておくだけでも、その運命を避けるのに役立ちます。