データベースの設計

/web/server-side

Note: この記事は、3年以上前に書かれています。Webの進化は速い!情報の正確性は自己責任で判断してください。

あるシステムにDB(データベース)を実装しようとする場合、RDBMSにOracleを使うかMySQLにするかPostgreSQLを選択するかってのもあるけど、まず実際どういうDBにするのか設計すると思う。Sig.の場合、設計時のコンセプトは次の2つ。

  • 重複を避ける
  • 求めるデータを「特定できる」ようにする

DB設計を厳密に行う手法には「リレーションの正規化」というものがある。これはデータの一貫性を維持し、不整合と冗長性を避け、効率的なアクセスを可能にするための設計手法。単に正規化ともいう。正規化には幾つか段階があるけど、実務の際には第三正規形までに止めて、それで十分とする場合が多い。その場合のポイントは、大まかに3つ。

  1. 繰り返しを避け、分割する
  2. キーと非キーに分ける
  3. キーとなりうる項目を分割する

あらかじめSQLでデータを取得することに慣れていると、設計から入るより楽に覚えられると思う。

定義

第一正規形
データの繰り返しグループを排除した形。繰り返し部分を複数のテーブル/レコードに分割する。
第二正規形
第一正規形から「キーから非キー」への関数従属性を整理した状態。候補キーに対して他の値が完全従属し、キーがこれ以上分解できない状態。
第三正規形
第二正規形から「非キー属性間」の関数従属性を取り除くことによって得られる。第三正規形では、キー以外の項目も全部眺めて、キーにできる項目を、片っ端からキーとして別の表に分離していきます。

関数従属: 「ある項目が定まると他の項目が定まる」という関係のこと。Aという値を定めるとBという値が決まる場合、「A→B」と表記し、「BがAに関数従属する」という。

手順

↑初期のDB案。アルバム名と価格が繰り返されている。

↑第一正規形。商品単位で分割し、レコードのキーとなる番号を追加。

↑第二正規形。商品番号に従属する各項目を、別のテーブルに分割。

↑第三正規形。アーティスト名はキーとして使えるので、分離する。こうすれば、アーティスト名からアルバム一覧を得ることができるし、そういった利用法も考えられるので分ける意義がある。

多重度

テーブルとテーブルが「1対多」であるか「多対多」であるか、といった関係性もまた重要になる。例えばSNSっぽく次のような場合。

グループは複数のメンバーを抱え、メンバーは複数のグループに所属できる。このとき、グループ・テーブルとメンバー・テーブルは「多対多(many-to-many)」の関係にあると言える。

一般的に多対多のリレーションは構築が難しい。たとえば「グループA」に所属している「メンバーの一覧」を出したい場合はどうするか。各メンバーのレコードからグループAの「グループID」に相当するキーを探し出し、一致すればリストに加える。ここで面倒なのは、メンバーがグループに幾つでも所属できる場合。

たとえば所属できるグループが「3つまで」と定められているなら、メンバー・テーブルのカラムに「所属グループ1」「所属グループ2」「所属グループ3」といった意味合いのカラムを用意すれば事足りる。しかし幾つでもとなると、メンバーが新しいグループに所属するたびにカラムを作成しなければならなくなる。

できないことはないけど、これはマズい。なによりスマートじゃない。ユーザがアクションを起こすたびにDBの構造が変化することになるし、殆どのユーザが1つか2つのグループにしか所属していないとしても、99個のグループに所属するメンバーが一人いるだけで、全てのメンバーに99個のカラムが用意されることになってしまう。明らかに資源の無駄遣い。ではどうするか?

「所属」という関係性を記録するテーブルを用意してやれば良い。「グループ」と「メンバー」は所属テーブルを通して接続する。「グループと所属」「メンバーと所属」はいずれも「1対多(one-to-many)」の関係にある。

こうすればメンバーの所属グループが幾つ増えようと「所属テーブル」のレコードが増えるだけ。その逆も然り。この状態では、「所属テーブル」に対して検索をかけてやれば、所属メンバーの数でも所属グループの一覧でも簡単に得ることができる。

そんな一例。

Note: スパム対策が面倒なので、コメント投稿を廃止しました。以前のコメントは残します。
ご意見・ご要望はtwitter@sigwygかはてブコメントにて。

4 Comments

road wrote:
DBの設計までなさっておられるのですか。すごいですね。

以前仕事でDBの設計をしたときに使用したツールがあるのですが、
リレーションを考える上でとても重宝したので参考までにどうぞ。
ただリレーションを記録するXMLがなぜか破損して
悲惨な目にあったりもしたのであまり信用はできないかも。。。
DBDesigner
http://www.aglabo.com/agl/proevo/software/fabforce/
http://dbdesigner.iimp.jp/ 2007–09–17 02:06
Sig. wrote:
いやあ、まだ負荷とか気にする必要の無い中規模システムの話なので、本当に「設計」と言えるレベルではないのですが^^; まあ、いずれは...!

> DBDesigner

おぉ~、ちょうど次から使おうと思ってたんですよ!
今のところはExcelで書いてたんですけど、これはリレーション記述できるわSQL文吐けるわで、注目してました。使い勝手はどないでしょ? 2007–09–19 05:30
road wrote:
ER図を作成するのは特に問題なかったかと思います。
カラムごとにコメントがかける機能は結構重宝しました。

実際に使ったときは、SQLを吐き出すのではなく、
データベースに直接DBDesignerがアクセスして
テーブルを同期させるということを行っていたのですが、
そこがちょっと不安だったかも。
あとPostgreSQLは対応してなかった気がします。(使ってたのはMySQL)

あと気になったのが、細かいことは覚えていませんが
操作性が悪いところが少しあったと思います。
テーブルのコピペをしようとしてできなかったんだっけかな・・・。

「見る」ツールとして使うなら十分じゃないかと思います。 2007–09–20 01:44
Sig. wrote:
うちはMySQLおんりーなので、OKです!
ふむふむ、同期は怖いですね... しかし見やすく、
SQL文吐き出せるってのは、やはり魅力的。

次から使ってみまっす。
Excelとどっちが使い勝手良いかな? 2007–09–25 13:44