データベースの正規化をお寺と仏像で考えてみた

目次

こんにちは。

データベースの設計の学習の中で出てくる正規化がちょっと楽しかったので、色々調べてみました。それをできるだけ簡単にまとめたいと思います。

データベースの正規化ってなんだ

早速引用で始まりますが、wikipediaでは関係の正規化のページでこうあります。

データベースにおいて、正規形と呼ばれる形式に関係(リレーション)を準拠させることにより、データの一貫性の維持と効率的なデータアクセスを可能にする関係設計を導くための方法 正規形には様々なものが存在するが、いずれにせよ、正規化を行うことにより、データの冗長性と不整合が起きる機会を減らすことができる。

つまりデータベースを正規化することで、データをシンプルにわかりやすく扱えるようにするってことですね。

関数従属性

さて正規化を考えていく上で重要なデータの関係性に関数従属性というのがあります。

まずはこれを理解した上で、正規化を考えていきたいと思います!

関数従属性

20181205-1.png

このような旅行関係のテーブルがあったとしましょう。

上のテーブルで例えば寺院が決まれば本尊も決まるので、"本尊は寺院に関数従属している"と言えます(本尊とはお寺の一番の信仰対象であり、お寺に一つです)。寺院が"東大寺"と決まれば本尊は"盧舎那仏"に決まりますよね。ちなみに"るしゃなぶつ"って読みます。

ただしその逆の"寺院は本尊に関数従属している"とは言えません。なぜなら表を見てわかるように釈迦如来(しゃかにょらい)を本尊としているお寺は複数あり、特定できないからです。

まとめるとある値を決めたときに別の値も1つに決まるような関係にある時に関係従属性がある、ということです。

推移的関数従属性

言葉にすると、Xが決まってYが決まる。Yが決まったので、Zが決まる。

先ほどのテーブルではtour_code → guide_code , guide_code → ツアーガイドの関係が成り立つため推移的関数従属性を持ちます。tour_codeが3に決まるとguide_codeが1に決まり、ガイドさんはAさんに決まります。

この理論は三段論法みたいですよね。しかし推移的関数従属性が成り立つためにはX → Zが成り立ってはいけません。

なぜならツアーガイドさんはguide_codeに紐づいており、tour_codeには紐づいていません。

どういうことかというと、guide_codeはtour_codeに関数従属していて、ツアーガイドもguide_codeに関数従属しています(guide_codeが決まればツアーガイドさんの名前も1つに決まりますよね!)。でもtour_codeによって直接的にツアーガイドさんが1つに決まるわけではないのです。

つまりtour_codeが決まって、guide_codeが決まって、それからツアーガイドが決まるという、ステップを踏むときに推移的関数従属性を持つ、と言えます。

このあたりがややこしいんですよね。

正規化

ここからようやく正規化の話に入っていきたいと思います。

非正規形

20181205-1.png

先ほどと全く同じテーブルです。まあ一見、表としてまとまっているようにも見えますが、データベースにデータとして保存するには良くない形をしています。

なぜ良くないかと言いますと、Excelのセルに当たる部分は全部別れていることと、セル中の情報は1つであること、が大切だからです。大切というかマストですね、マスト。

上のテーブルを見るとセルの中の情報は1つですけど、"釈迦如来"、"奈良"、"京都"のデータが入っているセルは結合しています。

このように、データベースに入れるのに最低限の形式すら持っていない形が非正規形です。

第一正規形

先ほどのテーブルのままではデータベースに入れることすらできません。そこでデータベースに入れるために、第一正規化するとこうなります。

20181205-2.png 変わったところは"釈迦如来"、"奈良"、"京都"がバラバラになったということだけです。

これにより、データベースでこれらのデータを扱えるようになりました。

第三正規形

本来ならば第一正規形と第三正規形の間には当然第二正規形があるのですが、表を簡単にした都合上、第二正規化ができないので省きます(第二正規化をする要素がない)。かいつまんで説明すると、第二正規化は部分関係従属する部分を別テーブルに分けることです。

tables

これで推移的関数従属性を持つテーブルはなくなりました。主キーが定まれば列の全ての値が定まるというテーブルとなっています。

具体的にはtour_tableではtour_codeが決まれば寺院とguide_codeが決定。

temple_tableでは寺院が決まれば本尊とエリアが決定。

guide_tableではguide_codeが決まればツアーガイドが決定。

これで先ほどのようなtour_code → guide_code, guide_code → ツアーガイドといった推移的関数従属性がなくなりましたね!

この形が第三正規形です。ちなみにtour_tableとguide_tableと関連づけるためにguide_codeをtour_tableに外部キーとして記入しています。

第三正規形以降の正規形

第三正規形以降もボイスコッド正規形、第四正規形、第五正規形と続くのですが、テーブルがあまりにも細分化されるためにかえってパフォーマンスが低下するそうです。いちいちデータベースにアクセスするためにSQLが大量発行され速度の低下を招きます。

そのため通常の正規化では第三正規形までに留めます。

conclusion

データベースの正規化はデータを扱いやすくすることで、効率をあげる!

第三正規化は推移的関数従属性をなくす!(つまり関数従属性だけにする!) まだまだプログラミング学習中なので、もし間違っている部分があれば教えてくださると嬉しいです。

【プチ情報】テーブルのお寺は奈良と京都の人気順に並べました。京都の人気の寺社仏閣としては伏見稲荷大社という、千本鳥居で有名なスポットがあるのですが、神社なので本尊がなく、今回は表から省きました。