« 関数従属性は多重度に先行して認識される | トップページ | テーブル関連を「コード」で構成することの是非 »

2006.09.03

代理キーは「スタイル」ではなく「テクニック」

 データモデリングでは、複合キーに代わって単一項目の代理キー(サロゲートキー)を導入することがある。これは「モデリング上のテクニックのひとつ」ではあるが「モデリングのスタイル(基本方針)」とみなすべきではない。その根拠を説明しよう。

Dbsample1 まず、倉庫が複数あるとして、倉庫にはさまざまな商品が保管されるとする。それぞれの商品は倉庫毎の特定の棚に保管される(つまり、商品と倉庫の組み合わせで棚が決まる)ことになっているとする(在庫管理では典型的な業務要件だ)。この関係をデータモデルで表すとモデル1のようになる。横浜第1倉庫でA01の棚に保管されることになっている商品100の現在庫が250個であることが示されている。

Dbsample2 このモデルをサロゲートキーにこだわって変形するとモデル2のようになる。

 2つのモデルの形式上の違いはどこにあるのだろう。モデル1では、倉庫コード、棚記号、品番が一次識別子として置かれているゆえに、それらについてヌル(空値)は許されない。また、テーブル内で値が重複してもいけない(ユニーク制約)。値を変更することも基本的に許されない。

 サロゲートキーにこだわったモデル2では、形式的には倉庫コードも棚記号も品番も「他の行との関係は気にせず、お好きに値を設定してください」といった位置づけの項目、つまりただの「属性項目」である。ブランクのままでもよいし、値が他と重複してもかまわないし、値を変えたくなったら変えても良い。いっぽう、倉庫id、棚id、商品idの各項目は一次識別子なので全行中で重複しないし、ヌルは許されないし、値が変化することもない。ただし、意味的にはモデル1での一次識別子と幾分違っていて、それらの項目はユーザからは見えないようにUI設計されることが多い。RDBMSで言うところの「レコード番号」のような位置づけである。

 ある種の分野では、このようなサロゲートキーの考え方は有効である。実際、筆者が公開しているモデリングツールXEADの内部リポジトリでは、「テーブルID」や「フィールドID」といった名前の「設定したければどうぞ項目」が使われているいっぽうで、「テーブルテーブル」や「フィールドテーブル」のそれぞれに、それらの項目とは別のサロゲートキーを付与した形のモデルとして実装してある。

 なぜそのようになっているかというと、XEADを利用する際に「テーブルID」も「フィールドID」も、コンテンツの編集過程で値がどんどん変化するからである。そういうものを識別子として置けば、コンテンツの編集操作が不必要に複雑になってしまう。どうしても、値が変わらないしユーザーからも見えないようなサロゲートキーが欲しくなる。

 ひるがえって、この考え方が在庫管理のような業務分野で有効であるかどうかはビミョーである。まず、倉庫コードを「お好きに値を設定してください」とすることには何も問題がない。そもそも倉庫コードなんてものが業務の現場で利用できなくても問題はなさそうなので、属性としても除いてしまってもかまわなくらいだ。けれども、棚記号や品番を使わないと在庫取引作業はやりにくくてしょうがないだろうから除くわけにはいかない。では、それらを形式が示すとおり「お好きに値を設定してください」としてよいものだろうか。それはまずい。なぜなら、それらがブランクだったり、重複していたり、値がコロコロ変わったりしたら在庫管理の現場は混乱するからだ。

 たしかにモデル2なら、棚記号や品番の体系が変化した場合、システム上ではデータ項目の値を修正するだけで対応できる。しかし、それを以って「業務上の『変化』に対応しやすいDB設計」と説明されてもなんだかそれは違うという気がする。品番の体系を変えてしまうというのは、システム上の対応の難易度とは別に業務上の大問題である。基本的に、品番などの重要なアイデンティファイアがコロコロ変わるような不安定なコード体系を設計しないことが肝心である。

 じつは「サロゲートキーにこだわるモデリングスタイル」には、目立たないがやっかいな問題がある。複数のidが複合してユニーク制約を構成している事実を見落としやすい点だ。

 たとえばモデル2では{倉庫id、商品id}のユニーク制約が存在するが、いきなりサロゲートキーを使ったモデルを描き始めるとこれを見落としやすい。この制約を見落とせば、倉庫idと商品idの値の同一の組み合わせが複数レコードとして存在する事態を招く。結果的に、遵守すべき関数従属性をデータベース上で保障できなくなる。実際、同業者の友人が最近かかわったそのような事例では、各テーブルに必要なはずのユニーク制約の8割が見落とされていたそうだ。相当にデータモデリングや業務知識に通じた技術者にまかせないと怖い。

Dbsample3_1 参考までに、単一項目で識別キーを作るという方針が明らかにそぐわないサブジェクトがあることも指摘しておきたい。モデル3の各月次取引サマリの識別子を単一の「ナントカ月次取引サマリid」とかに置き換えるなんてどう考えても尋常じゃない。年月等のタイムバケットが組み合わされた識別子に関数従属する項目が、業務システムではこのように大量に存在する。それらをすべてサロゲートキーで構成するのはいかにも無理がある。

 結論としては、適切なデータモデリングの手順は次のようになる。まずは、複合キーを含むオーソドックスなスタイルでモデリングする。その後で、必要に応じてサロゲートキーを導入してモデル全体を微調整する。つまり、「サロゲートキー」はデータモデリングの過程全体に浸透する「スタイル」になり得るものではなく、あくまでも局所的に手練が用いるべき「テクニック」である。これを統一的なスタイルとして無理やり導入してしまえば、わかりにくいか、そうでなくても危うさの潜むDB設計が生み出される危険性が高くなる。

|

« 関数従属性は多重度に先行して認識される | トップページ | テーブル関連を「コード」で構成することの是非 »

コメント

わたなべさん、いつも勉強させていただいております。コメントありがとうございました。

確認ですが、例中の在庫テーブルでは商品S100に対する棚IDは必ずA02になっていますが、倉庫によってはA01やE03の場合もありうるということですね。いずれにしてもモデル2はちょっとおかしいように思いますが・・・

「在庫数の管理」と「商品をどの棚に置くかの管理」を一つのテーブルでまとめて行おうとしている点に無理を感じます。モデル2では在庫テーブルの棚IDをなくし、別に「倉庫棚商品」テーブルを作るのが普通のやり方ではないでしょうか。

わたなべさんほどの業務経験がない分、まだ要件を取り違えているかもしれませんが・・・

投稿: bottleneck | 2006.09.03 18:45

bottleneckさん

「ある商品のある倉庫における現在庫数量」と「ある商品のある倉庫における棚」は、同一の識別子{商品、倉庫}に関数従属する項目です。ゆえに、これらは同じテーブルの属性項目とみなせます。データ項目のライフサイクルが違いすぎる場合にはテーブルを分けることもありますが、そういう意味でもこの場合は分ける必要はありませんね。

投稿: わたなべ | 2006.09.03 20:46

個人的には、単品を商品(カタログ)と倉庫・棚(ロケーション)でサマリーして管理しているが在庫とセマンティスクを考えてしまいます。わたなべさんのモデルはIDを中心とするシンタックスを中心に作成しているように感じます。メリットデメリットはあると思いますが、実際にもモデル作成においてシンタックス中心でセマンティスクについてはありまり考慮しないほうが実用的なのでしょうか?

投稿: dotnetmemo | 2006.09.03 23:12

あ、そのとおりですね。申し訳ありません、私のコメントが外してました。依然として、なぜ「棚」テーブルのidでなく「倉庫棚」テーブルのidが在庫テーブルに使われているのかは納得いってませんが、それもよく考えてみると問題の本質ではありませんね。

わたなべさんはユニーク制約を見落としやすいことを問題として挙げられていますが、それはユニーク制約をつけておけば解決するのではないのでしょうか?

投稿: bottleneck | 2006.09.04 00:38

dotnetmemoさん

> 個人的には、単品を商品(カタログ)と
> 倉庫・棚(ロケーション)でサマリーして
> 管理しているが在庫とセマンティスクを
> 考えてしまいます。

これの意味がちょっとわからないのですが、言われるとおり私はシンタックス先行でモデリングすべきだと考えています。多様で複雑な業務要件が相手でも関数従属性にフォーカスすることで、帳簿組織を描くための「とりあえずの理解」が得られるからです。もし意味論的な理解のうえでしかモデルを描けないとすれば作業効率が悪すぎます。もちろん意味の理解も必要ですが、とっかかりにはしないほうがいいと思いますね。

bottleneckさん

必要なユニーク制約が抜け落ちていないのであれば、問題はありません。けれどもそれを狙うのであれば「複合キーにもとづくデータモデリング」を実施したうえで形式的な調整を施すという手順を踏んだほうがよほど仕事が早いと思うわけです。

投稿: わたなべ | 2006.09.04 07:22

わたなべさん、コメントありがとうございます。
>多様で複雑な業務要件が相手でも関数従属性にフォーカスすることで、帳簿組織を描くための「とりあえずの理解」が得られるからです

上記は、多くの経験からのコメントだと思いますが、わたなべさんのモデリング手法のポイントなんでしょうね。
(わたなべさんの手法は、他のDOAよりもエンティティの意味論を重要視しないように感じていて、違和感があったのですが、なんとなく考えの一端が分かったように思います。ありがとうございます)

モデル作成時に意味論をどのようにするかについては
個人的には複雑なドメインに対しては意味論を考えることで、複雑さをコントロールしやすく安定するメリットもあると感じています。
ただ、ご指摘の効率面の問題もあり、パターン化などの工夫をしていますが、実務面での難しさも感じており、今後の課題となっています。

在庫についての解釈として以下のように考えてみました。
http://d.hatena.ne.jp/dotnetmemo/20060831/1157034035

本題からはずれた内容ばかりではもうしわけないので、サロゲートキーについてコメントしておきます。

基本的にはわたなべさんと同じで、サロゲートキーは実装テクニックだと考えています。複合キーでなくてもサロゲートキーをレコードIDとして利用します。
分析時にはキーはドメインのエンティティの管理単位や関係を調べる非常に重要なものなので、分析レベルでサロゲートキーを利用することは避けるべきだと考えす。

投稿: dotnetmemo | 2006.09.04 08:53

少なくとも今回例示いただいたモデルを見ただけだと、わたなべさんの「複合キーに基づくデータモデリング」というのが私にはむしろ難しく感じたのですが、そこまでいくと立ち位置の違いというだけのことなのかもしれません。

長々とお付き合いいただいてありがとうございました。

投稿: bottleneck | 2006.09.04 14:25

dotnetmemoさん

 DOAの方法論は、大きく構文論と意味論にわけられるようです。

 構文論はRDBの生みの親であるコッドがとった方法です。項目と項目の関係従属性を整理してテーブルを組み立てます。渡辺さんの方法はまさしくこれでしょう。意味論から見ると気持ちが悪い属性でも同じテーブルに入れる事に躊躇されません。

 意味論はチェンが元祖だと思ってます。エンティティ(実体)をまずとらえて、そのエンティティとエンティティの関係(従属性)を組み立てようという方法です。チェン自身の論文では、リレーションシップはキーの関係で示していましたが、今ではもっと自由にモデル化する手法もあります。

 ただ、構文論は裏に意味論がないと業務が定義出来ません。三要素分析法のDFDです。また意味論は構文論の前提がないと無意味に複雑怪奇なモデルを作ってしまいます。DOAの素養のない人がオブジェクト設計をやって失敗するパターンです。結局排他的でなく裏表の関係なのだと思ってます。

 私は学者ではありませんので、真理を追究する気はありません。しかも節操がないので、業務やお客様を見て、使いやすい方を使ってます(笑)

 業務分析をする前提として「項目」というものは必ずありますから、構文論で進めれば時間はかかってもいつかは結論が出るという安心感があります。抽象的な「エンティティ」なり「クラス」なりで会話を始めると、上手く行けば速いですが、設計途中で誤解がわかり後戻りする危険性があります。ユースケースやシナリオで抑えられる程度の業務なら意味論で行っても恐くはありません。

投稿: HAT | 2006.09.06 04:35

HATさん

仕事の進め方を理解することが「構造」に対する「意味」の補足に相当するものということですかね。何となくわかります。「識別子になり得るものは何だろう。それに関数従属する項目は何だろう」という単純で安直で形式的な手がかりにもとづいて分析を進めると、必要な帳簿組織の構造がわかってくる。でも、これだけではUIはわかりません。仕事の進め方(業務マニュアル)を分析して、それらを突き合わせてはじめてUIを導けます。構造と意味の理解は、それぞれ適切な手法を用いて両立させないといけないという感じはありますね。

投稿: わたなべ | 2006.09.06 17:02

コメントを書く



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




トラックバック


この記事へのトラックバック一覧です: 代理キーは「スタイル」ではなく「テクニック」:

» [DB設計]主キーにサロゲートキーを使うことの是非 [ITビジネス&テクノロジー]
設計者の発言: 代理キーは「スタイル」ではなく「テクニック」 主キーとしてサロゲートキーを使うと具合の悪いケースのご説明だと思うのですが、モデル2についての疑問が2つ。 1.なぜ棚テーブルが別テーブルになっていないのか? モデル2の想定だと、在庫テーブルがと... [続きを読む]

受信: 2006.09.03 12:43

» [db][datamodeling]代理キーとかサロゲートキーとか。 [たこわさRR]
恐れ多いですが、渡部さんのモデルに対しての自分の意見を。 要件はこんなところですね。 倉庫が複数あるとして、倉庫にはさまざまな商品が保管されるとする それぞれの商品は倉庫毎の特定の棚に保管される(つまり、商品と倉庫の組み合わせで棚が決まる) こんな感じになり... [続きを読む]

受信: 2006.09.04 17:51

» [DB設計]続・主キーにサロゲートキーを使うことの是非 [ITビジネス&テクノロジー]
前回の続きです。 設計者の発言: 代理キーは「スタイル」ではなく「テクニック」 理論的な話になると難しくてわからないので、とりあえず私も理解を深めるためにER図を描いてみようかなと思いました。 わたなべさんの問題の要件は以下の通りだとします。 倉庫が複数あるとし... [続きを読む]

受信: 2006.09.06 21:29

» [db][datamodeling]代理キーとかサロゲートキーとか。の続き [たこわさRR]
id:bottleneckさんからトラックバックをもらいました。 ぐはあぁぁあ。 1つの棚に複数の商品が置けてもいいつもりだったのに、 1つの商品しか置けないモデルになってしまってますね。 というわけで考え直しました。 改善版 わたなべさんとid:bottleneckさんのモデルとの違... [続きを読む]

受信: 2006.09.07 13:32

« 関数従属性は多重度に先行して認識される | トップページ | テーブル関連を「コード」で構成することの是非 »