Hot Heart, Cool Mind.

会計×IT の深層へ

主キーの設計②-正規化って何ですか?

主キー論争の分析その②である。
前のエントリーでは、最終的にできあがるデータベースの形について検討した。僕の結論は、内部識別子(アソシエーションの実装用の識別子)としてIDを用いることについては、コード派もID派も同意できるのではないかというものだった。
僕としては、コード派とID派の違いは、むしろ、今回検討するデータ設計の方法論に関するものだ、と思っている。


もっと具体的に言おう。誰でも、コッド博士が作り出した正規化の理論に忠実に従おうとすれば、ほぼ間違いなく「コード派」になってしまうのだ。なぜなら、正規化の数学理論には、IDとか(IDのウラにある)エンティティという概念が登場する余地がないからである。

正規化の理論の正確な意味(数学的な意味)は、設計の現場では明確には意識されていないし、意識しなくともデータベース設計はできてしまう。しかし、コード派とID派の論争のみなもとはここにある(と僕は考える)のである。

正規化のステップについて確認しよう:

  1. 正規化したいリレーションをひとつ採りあげる。
  2. そのリレーションにおいて見出せる関数従属性を洗い出す(関数従属性とは、「XごとにYが定まる」という形で表現される項目間の依存関係である)。
  3. 関数従属性をもとに各種の「正規形」の要件を満たすようリレーションを分解する。

これを見れば明らかなように、正規化とは、何かのリレーション、平たく言えばデータ表、を分解していく手続きだ。だから、もとのデータ表にないデータが正規化の過程で付け加わることはありえない。IDは(前のエントリで定義した)「内部識別子」機能をはたすだけで、ユーザの目に触れないデータ項目だから、もとのデータ表上には存在しない。したがって正規化後のデータ表にも存在し得ない。証明終わり。

しかし、と読者は思うだろう。「関数従属性」を発見するには、各項目の背後にある何らかの概念を想像するしかないはずだ。従業員名は従業員コードに関数従属する(すなわち、従業員コードごとに従業員名は一意に定まる)という場合、僕らが本当に言いたいのは、「従業員ごとに従業員名は一意に定まる」ということじゃないのか。表面的には「従業員コード」と「従業員名」の関係について話しているのだが、その背後には、あるいは、それに先行して、「従業員」と「従業員名」の関係が存在する。当然のことじゃないか。であれば、「従業員」に代表される「エンティティ」の概念が正規化の理論に登場しないはずはなく、実質はエンティティ参照である「ID」もどこかに居場所があるべきだ。

僕も心情的にはそのような主張にまったく賛成だ。しかし、正規化の数学理論における「関数従属性」はそういったものではない。データ項目の背後にある「実体(=エンティティ)」を一切仮定することなく定義されているのである。ちょっとわかりにくいと思うので例で説明しよう:

主キーサンプル①-商品テーブル

このリレーションで見出される関数従属性は以下の通りである(書式「X→Y」は関数従属性「XごとにYが定まる」を表す。またこのときXを「決定項」と呼ぶ):

  • 商品Cを決定項とする関数従属性:
    1. 商品C→商品名
    2. 商品C→単価
    3. 商品C→商品区分
    4. 商品C→商品区分名
  • 商品名を決定項とする関数従属性:
    1. 商品名→商品C
    2. 商品名→単価
    3. 商品名→商品区分
    4. 商品名→商品区分名
  • 単価を決定項とする関数従属性:
    1. 単価→商品区分
    2. 単価→商品区分名
  • 商品区分を決定項とする関数従属性:
    1. 商品区分→単価
    2. 商品区分→商品区分名
  • 商品区分名を決定項とする関数従属性:
    1. 商品区分名→単価
    2. 商品区分名→商品区分

「商品名を決定項とする関数従属性」も妙だが、もっともわかりやすく変なのは「単価を決定項とする関数従属性」だろう。単価が決まれば、商品区分名が決まる? そんなばなな。(-_-)。 なぜこんなのが関数従属性なのだろうか。数学的な意味での関数従属性は、与えられたリレーションのみを材料として定義されているからである。今扱っているリレーションでは、単価が100の行では商品区分名は「仕入品」、単価が200の行では商品区分名は「製造品」、単価ごとに商品区分名は一意に定まっている。 したがって、商品区分名は文句無く単価に関数従属しているのである。なお、リレーションとは表の見出し(項目名のならび)と内容をあわせた概念であることに注意して欲しい。見出しだけでは関数従属性を数学的に定義できないので正規化もやはり定義できないのだ。

ここまでの話でご理解頂けたように、数学的な意味での関数従属性は、個々の関数従属性が表す「意味(現実世界での妥当性)」に踏み込まないという意味で、形式的であり、リレーションとして与えられたデータ内容に縛られるという意味で、限定的である。あまりに形式的で限定的なので、実際のデータベース設計ではそのまま使えないほどだ。

そこで、設計の現場ではふつうどうするかというと、正規化の理論の半分だけ残して半分を捨てるのである(意識してか無意識のうちにかは問わず)。
すなわち、正規化の二つ目のステップで、関数従属性を、与えられたリレーションから抽出するかわりに、別途、ドメイン知識(対象業務領域に関する知識)をもとに洗い出す(脚注①)。三つ目のステップでは、関数従属性が何にもとづいて認識されたかは問われないから、理論どおりにリレーションを分解することができる。
このように二つ目のステップを改変したとしても、正規化理論の価値は残る。なぜなら理論は、三つ目のステップでリレーションを分解する際に適用可能な一般的手順を提供してくれるからだ。

ドメイン知識においては従業員コードや従業員名といったデータ項目だけではなく「従業員」という概念(エンティティ)が存在することが明確に認識されている。しかし上記のようにステップを改変してドメイン知識を活用することにしたとしても、エンティティの概念を正規化の数学的枠組みに持ち込んだことにはならない。単に正規化の枠組みの外で関数従属性を抽出する際に登場するだけである。したがって、依然として正規化の枠組みの中でエンティティやIDを取り扱うことはできないのである。

正規化理論はすっきりしているだけでなく、実務上も強力である。だから、僕は正規化理論を重視する。その点で僕は、コード派の一員とも言える。しかし、実装者としての僕は、最終的にできあがるデータベースにおいては、内部識別子としてIDを用いたい。その想いと、正規化ではIDを取り扱えないという事実の矛盾は、僕を不安定な状態に置き去りにするのである。
困った、困った。

さて疲れたので今日はこれくらいにしておこう。次回は、「じゃあどうすればいいのよ?」というところまで行けたらなあ。

(脚注①)
だからといって、数学的な意味での関数従属性の概念が実務上は無意味だというわけではない。ドメイン知識にもとづく関数従属性は、数学的な意味での関数従属性でもあるはずだから、リレーションのデータが正しければ、ドメイン知識にもとづく関数従属性を検証するために、そのデータを用いることができる。