リレーショナルモデルにあるのはナチュラルキーだけ
リレーショナルモデルには「サロゲートキー(代理キー)」という概念はない。まずこの点に注意して頂きたい。サロゲートキーとは、データベースアプリケーション開発において実用上必要とされる機能であって、本質的には不要のものである。リレーショナルモデルでは、いわゆるナチュラルキーというものがあれば機能的には十分だからだ。そのためにはまず「キー」という概念が何を指し示すかということについて正しく理解しなければならない。リレーショナルモデルではキーと呼ばれるものは候補キーとスーパーキーという2つの概念だけである。「タプル(≒行)の値を一意に決定することができる属性(≒カラム)の集合」のことをキーと呼ぶ。このとき、集合が規約のもの(つまりそれ以上属性を減らすとキーとしての役割を失ってしまうようなもの)を候補キー、そうでないものをスーパーキーという。スーパーキーとは候補キーに余分な属性が含まれたものであると言える。規約であってもなくても「タプルの値を一意に決めることができる」という機能は同じである。ちなみに、本来の意味でのリレーション(≒テーブル)には重複したタプルは存在しないので、見出しの全体、つまり全ての属性を含んだ集合は必然的にスーパーキーとなる。こういった議論は先日公開したスライド でも述べているので、ぜひ復習して頂きたい。
リレーショナルモデルでは候補キーは集合なので、リレーショナルモデルに従ってデータをモデリングすれば、必然的に複合キーを使うことになる。単純キーか複合キーかといった議論もあるようだが、そういった議論は端からリレーショナルモデルの前提を無視したものであり、リレーショナルモデルを正しく理解しているならば論じるに及ばないことは分かるだろう。
「主キーはサロゲートキーにすべき」という議論は2つの問題をごっちゃにしている
「ナチュラルキーを主キーにしてはいけない」という命題は、裏を返せば「主キーはサロゲートキーにすべき」ということを意味している。本当にすべてのキーをサロゲートキーにすべきだろうか?先程述べたように、サロゲートキーはリレーショナルモデルでは本質的に不要なものである。不要なものをわざわざ使う必然性はどこにあるのだろうか。サロゲートキーの議論に関しては、ミックさんがコンパクトにまとめてくださっている。2分で読める記事なので、一旦本エントリを読むのは中断して、まずはそちらを参照して欲しい。(誤解の無いよう断っておくと、ミックさんの解説には何ら問題はない。本エントリでは理論的な側面について追記しているに過ぎない。)
第3回 テーブル設計のグレーゾーン~毒と薬は紙一重 (4)サロゲートキーVSナチュラルキー:SQLアタマアカデミー|gihyo.jp … 技術評論社
記事では、2つ目の例「主キーの値が使いまわされる場合」というのを図で解説されている。過去のitem_noが将来使いまわされているという例だ。
item_noとは一体何を表すデータなのだろうか。より具体的に言えば、item_noに入るべき値は如何なるものであろうか。さらにリレーショナルモデル的に言えば、item_noという属性の個々の値は、どういったドメインの要素のひとつなのかといい換えることができる。リレーショナルモデルでは、ドメインとは属性が取り得る値の集合のことである。(詳細はスライド を参照のこと。)もし同じ要素が異なるアイテムを指し示す可能性があるのだとしたら、そのドメインは一体如何なる意味のものだろうか。
結論からいうと、ミックっさんの記事にあるitem_noカラムは、ドメインの定義に失敗している例であると言える。つまり、そのドメインは「アイテムを一意に特定できるデータの集合」ではないということだ。ドメインの要素が複数の意味を持ちうるということは、その属性がキーに含まれるかどうかに関わらず問題であるので、どの道何かしらの対応をする必要がある。ここで、アイテムを一意に特定できるデータが存在しないのであれば別途そういうデータを追加すればいいではないかというアイデアが思いつくだろう。それがサロゲートキーと呼ばれるの背景にある考え方であり、つまり問題の根本はドメインの選択が適切でないという点に集約できる。
一方で、その新たに追加したカラムは果たしてそのリレーションのキーとして適切であるかどうかという話はまた別である。どのような属性の集合がキーとして適切かどうかというのは、テーブル設計の話である。ドメイン、つまり特定の属性(≒カラム)の設計の話ではないのである。主キーとして相応しいのは候補キーである。候補キーは、キーとしての働きを持つ属性の集合のうち規約のものであり、主キーがどれかということを検討するには、そういった組み合わせを見つけることになる。
ちなみに、リレーショナルモデルには主キーという概念はない。SQLでは主キーとそれ以外のユニークキーは区別されるが、リレーショナルモデルでは両者の区別はない。候補キーとなる属性の集合は、ひとつのリレーションに複数個存在する可能性があるので、それぞれに主キーあるいはユニークキーを割り当てることになるが、どれを主キーにするべきかということについては特に決まりはない。設計者が恣意的に選ぶ以外に方法はないのである。
本来あるべき対策
答えは実にシンプルだ。item_noの持つドメインが適切でないのならば、本来はそれを適切なものへと変更するべきなのである。具体的には、コードの標準化を行うという、データ品質のリファクタリングをすることになる。この作業の詳細については、書籍「データベースリファクタリング」で詳しく解説されているので是非そちらを参照して欲しい。現実には、リファクタリングは直ぐにはできない、リファクタリングに対するお客さんの理解が得られないといった諸事情があるので、そういった場合に回避策としてサロゲートキーをつけるという方法を用いることになる。ただし、そのような対応はあくまでもその場しのぎの回避策だと言える。
回避策はそれ自身悪いものではない。問題に直面した場合に恒久的かつ抜本的な解決策を適用できない場合、状況を改善することができるなら、選択肢として常に念頭に置いておくべきである。だが、回避策はあくまでも回避策であって、それが本来の正しいやり方だと考えるのは誤りである。回避策は確かに有効であるが、それをあたかも絶対的な法則であるように考えるのは、本来の用法を間違う原因になるだろう。言い換えると、バッドノウハウとすらなり得ることである。
本来はあくまでも適切なドメインを設計すべきであり、その上で適切に候補キーを選択すれば良いのである。(それはナチュラルキーと呼ばれるものになるだろう。)
適切なドメインの設計
そもそも、ミックさんの解説にあるitem_noも、明らかに人為的に割り振られた番号であり、元々は何かしらのサロゲートキーであった可能性が高い。あるアプリケーションで作成したサロゲートキーが、別のアプリケーション等でも利用していくうちに一意性が破綻してしまうということは十分あり得る話である。そういった意味でも、サロゲートキーさえ利用していれば全ての設計上の問題から逃れられるかのように考えるのは間違いである。最も重要かつ根本的な対策は、繰り返しになるが「ドメインを適切に設計する」ということである。リレーショナルモデルを使用する以上、それ以外の安易な解決策は存在しない。
ところが、これが非常に難しい。なぜなら、そのアプリケーションでどのようなデータが必要であり、それをどのようなデータ型で表現するか、ドメインにどういった要素を含めるべきかという設計には、絶対的な手法がないからである。アプリケーションがどのようなデータを必要するかは、一言で言えば要件次第である。要件を定義し、それをデータアイテムへ落とし込む作業は、人間が恣意的に判断しなければならない作業であって自動化することはできない。コンピュータに考えさせれば確実にフレーム問題にぶち当たる。もし自動化するなら人間と同等の能力を持ったAIが必要となるだろう。だがそのようなAIは存在しないので、人間が訓練を積んだ上で取り組む作業であると言える。
人間が行う作業である以上、完璧な設計というものは望めない。従って破綻した設計のドメインが生じる可能性は大いにあり得る。問題が生じたときに一時的な回避策を講じることに異論はないが、回避策はあくまでも回避策であって、データベース設計上は負債となって残ってしまうことになる。問題が生じる可能性があるからといって「全て事前に回避策をとっておくべきだ」という意見は乱暴であり、負債だらけの設計を生み出すだけであると言える。その結果、将来的に新たなドメインの設計破綻を生み出し、新たなサロゲートキーが必要になることだろう。そうなっては無限地獄である。
一方で、正しいドメイン設計ばかりに凝り固まってしまうのも実用的ではない。理想的なドメインをすべて洗い出すのは非常に時間がかかるからだ。納期などの状況を鑑みて、バランス良く活用していけば良いと思う。
重要な点は、本来どうやって設計すべきかということ、そして設計の問題に気づいたときにどうやってそれを一時的に回避するか、リファクタリングをして根本的な解決を図るにはどうすれば良いかということについての、正しい知識を身につけるということである。
1 コメント:
リレーショナルモデルにおける候補キーには一意性がありますが、不変性は特に言及はされていないのでしょうか?
コメントを投稿