Saturday, October 13, 2007

ある関数従属性をもつ属性に対してどのようなリレーションを作成すべきか?

この投稿、近いうちに削除します。もう少し、うまくまとめて再度アップするつもり。

正規化の議論は、あるリレーションが正しい構造か?更新異常がない構造になっているか?という観点からのもの。ここでは逆に属性をどのように組み合わせていけば正しい構造のリレーションになるかを考えてみる。

まず、2つの属性 A, B は次の3つの関係(リレーションシップ)を持ちうる。

  • 1対1のリレーションシップ。このとき、A → B かつ B → A の関係である。
  • 多対1のリレーションシップ。このとき、A → B かつ B NOT → A の関係である。
  • 多対多のリレーションシップ。このとき、A NOT → B かつ B NOT → A の関係である。


1対1のリレーションをもつとき。

この場合、A と B は少なくとも1つのリレーション R 上に共存しなければならず、A または B が R のキーとなる。A が B を決め、B が A を決めるということは、A と B がそれぞれ何らかのエンティティ・インスタンスを決定していると捉えて、そのリレーションをつくるわけだ。そして、ある属性 C をこの R に追加するには、A → C または B → C が成立しなくてはならない。また、データの不要な重複を避けるために複数のリレーションに A, B が共存することは避けるべき。リレーション間のリレーションシップを作るために A または B が他のリレーションシップに存在する場合はあるが(いわゆる外部キーであろう)、その場合、あるリレーションには A、もう1つのリレーションには B というようにはせず、A または B の1つのみを使うようにした方がいい。

多対1のリレーションをもつとき。

この場合、A と B はリレーション内で共存でき、そのときは A がそのリレーションのキーになる。ある属性 C をそのリレーションに追加できるのは A → C が成立する場合だけ。

多対多のリレーションをもつとき。

この場合、A と B はリレーション内で共存でき、そのとき、(A,B) がそのリレーションのキーになる。(A,B) → C が成立するときだけ C をそのリレーションに追加できる。ただ、(A,B) NOT → C でも、C NOT → (A,B) だとすると、この関係は (A,B) と C との多対多のリレーションシップである。したがって、C をリレーションに追加して、(A,B,C) をキーとできる。ただし、こうしてしまうと、もはやこのリレーションは違う主題を表していることになるので、リレーションの名前を変えた方がよいということになる。

ちなみに、上で C → (A,B) が成立としたら、関数従属性の性質から C → A かつ C → B が成立する。この場合、多対1のリレーションということで、C,A,B が共存することは可能であり、C がそのリレーションのキーということになるだろう。

このように属性を組み合わせてリレーションを作っていけば、それらは DK/NF を満たすようになるだろう。

上の多対多のリレーションで (A,B,C) をキーにする場合だが、こうできるのは、多値従属性 A →→ B | C または B →→ A | C が成立しない場合に限られる。そうでないと 4NF にならず、当然 DK/NF も満たさないから更新時異常が起こってしまう。

たとえば、R{ 教授名, クラス } というリレーションがあって、教授とクラスの組み合わせがキーだとする。授業をする教室が教授の気まぐれで決まるとしたら、使用教室、という属性と (教授名, クラス) とは多対多のリレーションシップをもつ。そして明らかに、ここには多値従属性はないので、{ 教授名, クラス, 使用教室 } をキーとした新しいリレーションをつくることができる。

ドメイン/キー正規形(DK/NF)

この投稿、近いうちに削除します。もう少し、うまくまとめて再度アップするつもり。

リレーションの更新時異常を解消していく過程で、1NF, 2NF, 3NF, BCNF, 4NF, 5NF と正規化が進んでいく。5NF まで正規化されると更新時異常は起こらなくなるので、5NF がある意味究極の正規形である。

この正規形の系列とは別にドメイン/キー正規形(DK/NF)がある。この DK/NF でも更新時異常は起こらず、また更新時異常が起こらないリレーションは DK/NF であることが示されている。リレーションが DK/NF であるための条件は以下のとおり。

「リレーション上のすべての制約条件がキーとドメインの定義の論理的な帰結である場合にそのリレーションは DK/NF となる」

制約条件とは、「属性の静的な値を決定するためのルールで、真か偽かを明確に決定できるもの」である。したがって、関数従属性や多値従属性、リレーション間・リレーション内の制約条件などが該当する。なお、「静的な値」なので時間に依存する条件は含まない。たとえば、セールスマンの給料を表す属性値を変更するときは前の値より多くなければならない、などだ。

ドメインとは、属性の定義域のことだ。物理的定義と意味的定義の2つの側面があるが、DK/NF では物理的意味だけを考えればいい。

DK/NF の利点は、ドメインとキーというデータベース実務者にとって基本的な概念のみに関連していること。リレーションのすべての制約条件がこの基本的な概念の論理的な帰結になっているかどうかをチェックすればいいので、1NF から 5NF の正規化よりもずっと理解しやすくなっている。

直感的には、リレーションが1つの主題のみをもつようにすれば、DK/NF になるだろう。

Tuesday, October 09, 2007

多値従属性と 4NF

この投稿、近いうちに削除します。もう少し、うまくまとめて再度アップするつもり。


多値従属性(MVD)とは関数従属性(FD)を一般化した概念。したがって、FD は MVD でもあるということになる。

A, B, C, X をそれぞれ属性の集合としたとき、リレーション R{A,B,C,X} 上で、値 (A値,C値) に対応する B の値の集合が A値によってのみ決まり、C値とは独立しているとき、B は A に多値的に従属する、または A は B を多値的に決定する、という。これを A →→ B と書く。

「A の値によってのみ決まり C の値とは独立」とはどういうことかというと、ある A値をもつタプルの集合における B値、C値の集合を考えたとき、その「B値の集合」と、「C値の集合のそれぞれの C値に対応する B値の集合」が一致することをいう。このことから、A →→ B であるとき、かつそのときに限り A →→ C でもあることが分かる。そこで、この関係を A →→ B | C とも書く。

ここで X が空集合だとしてみる。すると R{A,B,C} はすべての属性の組み合わせをキーとする BCNF なるだろう。このとき、関数従属性と更新時異常で述べたように、R には FD を原因とする更新時異常は起きないが、A →→ B | C の MVD を原因とした更新時異常が発生する。

これを解消するために R{A,B,C} は2つのリレーション {A,B} と {A,C} に無損失分解することができる。結局、BCNF であるリレーション R をさらなる正規形に分解できたことになるのだが、この新しい正規形を第4正規形(4NF)と呼ぶわけだ。

4NF とは、「BCNF であり、かつそこにおけるすべての MVD が候補キーからの FD であるリレーション」と定義できる。

ちなみに無損失分解とは、分解してできた新たなリレーションを結合したときに元のリレーションに戻せるような分割のことだ。結局、正規化とは、更新時異常を避けるためにリレーションを無損失分解することだといえる。

Tuesday, October 02, 2007

1NF, 2NF, 3NF and BCNF

この投稿、近いうちに削除します。もう少し、うまくまとめて再度アップするつもり。

関数従属性に関する正規形の種類。関数従属性と更新時異常 で書いたように、BCNF までいくと関数従属性に起因する更新時異常がなくなる。じっさい、1NF, 2NF, 3NF は BCNF までの踏み台にすぎない。

BCNF の上に、多値従属性に関する正規形 4NF と結合従属性に関する正規形である 5NF がある。

まず、1NF。すべてのリレーションは 1NF になる。つまり、属性は単一の値(スカラ値)を持ち、同一のタプルは存在しないといったリレーションの定義を満たすものはすべて 1NF である。

2NF とは、キー以外のすべての属性がキー上で既約従属(キーの一部の属性に従属しない)であるリレーションをいう。これは候補キーが1つだけの場合の定義になるが、上で述べたように BCNF までの踏み台にすぎないのであまり形式的にやる必要もないだろう。

3NF とは、2NF であり、かつキー以外のすべての属性がキーに推移的でない従属をしているリレーションのこと。推移的な従属とは、A → B かつ B → C ならば A → C のような従属のことだ。このとき C は A に推移的に従属している。3NF とはこの推移的従属がないものをいう。ここでも候補キーが1つしかない場合の定義になっている。

BCNF とは決定項がすべて候補キーになっているリレーションのこと。つまり、R 上のすべての関数従属性の決定項が候補キーでもある場合、R は BCNF である。

Monday, October 01, 2007

関数従属性と更新時異常

この投稿、近いうちに削除します。もう少し、うまくまとめて再度アップするつもり。

リレーション R 上の属性で、A が決まると B も決まるとき A → B と書く。このとき A を決定項、B を従属項という。決定項、従属項は属性の組み合わせでもよく、A → {B,C}、{A,B} → C、{A,B} → {C,D,E} もある。

A → {B,C} と A → B かつ A → C は同じことである。が、{A,B} → C と A → C かつ B → C とは同じではない。

A → A および {A,B} → A は自明。従属性を考えるときは自明な従属性は除いていい。

すべての属性が従属するような決定項をキーという。キーが複数の属性から成り立つ場合、その一部がそれ以外の部分に依存することがあってはいけない(既約)。キーでない、またはキーの一部でない属性を非キー属性という。キーは複数存在することもあるので、候補キーともいう。

ここで、関数従属性と更新時異常との関係について考えてみる。

データベースというのは「モデルのモデル」すなわち、現実のビジネスに対するユーザの見方(ユーザのデータモデル)のモデルであった。したがって、リレーション上の関数従属性もユーザのデータモデルを反映している。

更新時異常とは、更新したときにユーザのデータモデルと不整合を起こす、または不整合を防ぐために何らかの異常な操作をしなくてはならないことだと定義できそう。

候補キーでタプルを識別し、更新・削除することは、結局ユーザデータモデル上で対応するインスタンスを更新・削除することに対応する。リレーション上で更新・削除されるのも1つのタプルだけであり、異常はない。

しかし、キーでない関数従属性の決定項でタプルを更新しようとすると、ユーザモデルでは更新されるべきインスタンスが1つに決まるはずだが(ユーザの頭の中にあるビジネスの見方に矛盾がない限りそうであるはず)、リレーション上では1つに決まらず複数のタプルを更新しなくてはならない場合がある。挿入しようとしても、決まらない属性があるのでタプルが決まらず、リレーションに挿入することができない。

したがって、このような更新時異常は、リレーション上の関数従属性の決定項がすべて候補キーになっていれば起こらない。こういうリレーションが、Boyce-Codd 正規形であり、ここまで正規化されると、関数従属性に起因する更新時異常は発生しなくなる。