« 「強制されたサロゲートキー」の事例を眺める | トップページ | ショボいDB設計で突っ走るための50の方法 »

2012.02.10

サロゲートキーの事例解説

 前回の2つのモデルの違いがよくわからないと言われたので、補足しておこう。ただし私はことさらRailsやRedmineにケチをつける気はない。いずれも優れたツールで、これらを使いこなすためにも、サロゲートキーを組み込んだ場合のテーブル構造の特性を理解しておく必要がある。そのためのDB設計に関する一般的議論として参考にしてもらえばさいわいだ。

 2つのテーブル構造を簡略化したものが以下の2つのモデルである。実際のテーブル構造である(1)にもとづいて「予想」されたデータ要件が(2)、という関係にある。Redmineのもともとのテーブル名であるprojects, users, membersの具体的な意味合いやUIを勘案すれば、この予想はおおかた間違っていないだろう。なお図中の{ }は二次識別子を、attr1,attr2,...は属性項目(attribute)を表している。

(1):実際のテーブル構造

[A] id, attr1


└―…
┌―…[AB] id, attr4, {A-id, B-id}
|   +
|   |
|   └―…[ABC] id, attr5, AB-id, C-id
|   ┌―…
|   |
|   +
|   [C] id, attr3

[B] id, attr2

(2):予想されたデータ要件

[A] id, attr1


└―∈
┌―∈[AB] A-id, B-id, attr4
|   +
|   |
|   └―∈[ABC] A-id, B-id, C-id, attr5
|   ┌―∈
|   |
|   +
|   [C] id, attr3

[B] id, attr2

 じつは、(2)にサロゲートキーを導入すれば、(1)ではなく(3)のようになる。(3)ではテーブルABCに{AB-id, C-id}のユニーク制約が組み込まれているが、(1)では組み込まれていない。この違いは何なのだろうか。

(3):(2)にサロゲートキーを組み込んだもの

[A] id, attr1


└―…
┌―…[AB] id, attr4, {A-id, B-id}
|   +
|   |
|   └―…[ABC] id, attr5, {AB-id, C-id}
|   ┌―…
|   |
|   +
|   [C] id, attr3

[B] id, attr2

 私にはこの違いが、ユニーク制約を組み込むことを「忘れた」結果ではないかと思える。小さな差だがそのインパクトは小さくない。それは、attr5=F(A-id, B-id, C-id)の関数従属性の有無としてデータ状況に影響を与える。

 具体的には、(4)のデータ状況を(1)では許すが、(3)では許さない。(3)のテーブルABCでは、{AB-id, C-id}にユニーク制約が設定されているからだ。まあ、テーブルABCに相当するRedmineのmember_rolesにはたいした属性項目が置かれていないので、たまたま大きな影響を与えるものではないだろう。しかし、会計データを含むテーブルでこういうミスは許されない。

(4):(1)で起こり得るデータ状況の例

[A] id, attr1
+ 001 ...

└―…
┌―…[AB] id, attr4, {A-id, B-id}
|   +  001 ...   001 001
|   |
|   └―…[ABC] id, attr5, AB-id, C-id
|   ┌―…    001 1,500  001 001
|   |       002 2,000  001 001
|   +
|   [C] id, attr3
|     001 ...

[B] id, attr2
  001 ...

 凡ミスでないとすれば(2)の予想が間違いということになろうが、いずれにせよサロゲートキーが組み込まれることで本来の関数従属要件がわかりにくくなるということではある。歪んだ改修がされないように、本来の設計意図は保守担当者にしっかり申し送りされなければいけない。――つまりけっきょくは、データ要件のままでDBを実装できるのがいちばん楽なのである。「本来のデータ要件」を理解してもらうための努力も要らないし、ユニーク制約の組み込み忘れの心配もないからだ。

 そういうわけなので、最初から単独主キーだけでDB設計を進めるクセをつけてはいけない。関数従属要件の取りこぼしを避けるためだ。すなわち、まずは複合主キーを含めた形で論理設計を誠実にまとめる。その後で、実装環境に合わせてサロゲートキーを必要に応じて組み込む。そんな設計手順が「無難」だ。そもそもそこまで理解すれば、実装環境によってサロゲートキーが「強制」されることの異様さもわかるだろう。

 「データ構造が多少危うくとも、データの整合性を崩すようなプログラムを作りさえしなければよい」と思われるかもしれない。その意見は一面では正しいが、間違いでもある。少なくとも、「データの整合性はプログラムによって維持されるべきもの」と考えてはいけない。

 80年代中頃まではそれが常識であった。その姿勢を「POA(プロセス指向アプローチ)」と批判して登場した方法論が「DOA(データ中心アプローチ。英語ではDCA)」である。DOAでは「データの整合性は正しいデータ構造によって維持される」と考える。最初に確立されるべきものは「的確なデータ要件にもとづくデータ構造」であって、プログラムは脇役に過ぎない。なぜか。プログラムを主役にしてしまえば、保守されるべきコードが季節の巡りにつれて増えてゆくからだ。そして、コードの保守コストはデカいからだ。さらに、プロセスを立脚点とする限り、企業が管理すべきデータの統合的な構造は見えてこないからだ。

 残念ながら、DB構造が的確でありさえすれば開発プロジェクトの成功が約束される――という話ではない。しかし、DB設計に失敗すればプロジェクトは確実にコケる。少なくとも、まともなプロジェクトはまともなDB構造からしか始まらない。ここらへんの認識の重大さに比べたら、サロゲートキーの使い方なども瑣末な知識でしかない。

|

« 「強制されたサロゲートキー」の事例を眺める | トップページ | ショボいDB設計で突っ走るための50の方法 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: サロゲートキーの事例解説:

« 「強制されたサロゲートキー」の事例を眺める | トップページ | ショボいDB設計で突っ走るための50の方法 »