サロゲートキーと「とりあえずID」の違い
サロゲートキー(代理キー)は慎重になされる限り、有用なテクニックである。いっぽう、すべてのテーブルに機械的にIDを置く「とりあえずID(IDリクワイアド)」の設計スタイルでは、複雑なデータ要件を扱った途端にひどい目にあう(とくに保守担当者が)。両者の違いをしっかり理解しておこう。
何でもいいのだが、ここでは生産管理システムで見かけそうなシンプルなモデルを使って説明しよう(図1)。「作業区・品目」は、それぞれの作業区で生産可能な品目の組み合わせと、その品目を扱った際の生産性(時間あたり生産数)の管理簿である。
<図1>
+  ̄ ̄ ̄
| 001 切削 個
| 002 加工 m
|
└―∈[作業区]工程id,行番,作業区名,標準生産性
+  ̄ ̄ ̄ ̄ ̄ ̄
| 001 01 切削1号 1000/hr
| 001 02 切削2号 2000/hr
| 002 01 加工1号 10/hr
| 002 02 加工2号 20/hr
|
└―∈[作業区・品目]工程id,行番,品目id,生産性
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
001 01 0001 1000/hr
001 01 0002 1000/hr
001 02 0001 1200/hr
001 02 0003 1500/hr
002 01 0002 10/hr
002 01 0003 10/hr
002 02 0002 20/hr
002 02 0004 30/hr
このモデルでは、3つのテーブルが多段階の親子関係を成している。つまり、「子」の主キー(下線で示した部分)が「親」の主キーを包含した形になっている。図中に具体値で示したように、一般に親の1レコードに対して子の複数レコードが対応する。すなわち、親子関係の多重度は「1:多」となる。親子関係とはそういう関係のことをいう。
つづいて、複合主キーを含むこのモデルにサロゲートキーを組み込んで正規化崩ししてみよう(図2)。複合主キーが単独主キー(id)に置き換わって、代わりにいくつかの項目の組み合わせにユニーク制約({...}で示された部分 注1)が付与されている。結果的に、図1の2つの親子関係が参照関係に変化している。つまり参照関係とは、参照先への外部キー(参照キー)が「主キーに包含されない形」で置かれている関係のことだ。
<図2>
+  ̄
| 001 切削 個
| 002 加工 m
|
└―…[作業区]{id,工程id},作業区名,標準生産性
+  ̄
| 001 001 切削1号 1000/hr
| 002 001 切削2号 2000/hr
| 003 002 加工1号 10/hr
| 004 002 加工2号 20/hr
|
└―…[作業区・品目]{id,作業区id,工程id,品目id},生産性
 ̄
001 001 001 0001 1000/hr
002 001 001 0002 1000/hr
003 002 001 0001 1200/hr
004 002 001 0003 1500/hr
005 003 002 0002 10/hr
006 003 002 0003 10/hr
007 004 002 0002 20/hr
008 004 002 0004 30/hr
DB構造についてはこれでいいが、アプリに関して別途考慮が要る。ユニーク制約が付与されている属性項目について、その値を更新できないようにあえて設計されなければいけない。後述するように、これを怠るとデータの整合性が簡単に失われてしまうからだ。つまり正規化崩しすることで、DBの記述として完結していたデータ仕様の一部をわざわざ機能仕様に持ち込む羽目になる。結果的にコードが増えて保守性が低下するが、ある種の実装基盤ではこういった実装が求められるのでしかたない。まともにやれば、サロゲートキーは役に立つテクニックのひとつである。
いっぽう、これと似て非なるやり方が「とりあえずID」だ。図1の論理モデルを経由せずにいきなり実装プランを描き始める。思いついたデータのまとまりをテーブルとみなして、とりあえずIDを主キーとする。運よく図2と似た形になったとしても、なにしろ論理要件が了解されていないため、ユニーク制約や更新不可制約の配慮があちこちで漏れる。
たとえば、「作業区・品目」上の工程idが編集可能であるようなアプリがリリースされる。1件目の工程idが001(切削)から002(加工)に変更されたりすれば、その瞬間にデータの整合性が失われる。なぜなら「作業区」上では、作業区001の工程は001(切削)だと定義されているからだ。この更新時異状を避けようとして「作業区・品目」から工程idをはずしたとしても問題は解決されない。たとえば作業区1件目の工程idが001から002に変更されたとして、変更以前のデータ状況を想定した「作業区・品目」がそのまま放置される可能性を排除できない。ようするにこんな単純なモデルでさえ、「とりあえずID」のスタイルはさまざまな地雷をいつの間にかシステムに埋め込んでしまう。
「そもそもそんな不自然な変更操作をするユーザが悪い」と思われるだろうか。それはやつあたりである。いかに珍妙キテレツに思える変更要求であろうと、その操作がシステム上可能である限り、ユーザはいつかそれを実行する。もちろん理想的なシステムであっても、ユーザが間違ったデータを入力することは避けられない。しかし、データの整合性を失わせるような要求は拒否されなければならない。それがエンジニアリングされたDBシステムというものだ。
まあ、データ要件が単純な案件であれば「とりあえずID」の一本槍でしのげるだろう。しかし生産管理システムのように、複合主キーでしか構成できない複合概念(交差概念)がふんだんに扱われる案件ではそうはいかない。実装時にサロゲートキーを組み込むかどうかに関係なく、自然キーではない複合主キーを含むオーソドックスなデータモデルを確立しておかなければ、サロゲートキーの導入をはじめとするさまざまな正規化崩しに失敗する。結果的に、第三者にとって理解しにくいだけでなく、カットオーバー後にじわじわとデータが濁ってゆくDB構造が生み出される。
本来であれば、DB設計に関わるここらへんの基本知識は先輩たちから継承されるべきなのだが、たいていの現場にはそんな余裕がない。しかも、IDを単独主キーとして置くだけでなんとなくDB設計できている気分にもなるので、教わるほうも学ぶ必要性を感じなかったりする。かくしてそのしわ寄せはカットオーバー後の保守担当者にゆく。なにしろ正規形が申し送られていないので、問題が生じても何をどう改修したらいいかわからない。もっと気の毒なのがユーザ企業であることは言うまでもない。
ようするに、どんな実装上の制約があろうとまともにデータモデリングしようぜよ、という話だ。そのうえで、利用する開発基盤が複合主キーを認めてくれないのであれば、サロゲートキーやユニーク制約や更新不可制約を神経質に組み込めばいい。もちろん正規形のまま実装できる開発基盤を使えるのであれば、それがいちばん気楽だ。
注1.この場合、主キーだけでユニークになるので、主キーを含めてユニーク制約が付与されているのが奇妙に思われるかもしれない。ここではむしろ、「更新不可制約」を受ける項目を示すためのものとしてとらえてもらっていい。
| 固定リンク
この記事へのコメントは終了しました。
コメント