ログ日記

作業ログと日記とメモ

DBの複合主キーの話

複合主キーのエントリ http://d.hatena.ne.jp/torazuka/20110713/pk を見て、今机の上にあるERDを見たら結構複合主キーがあるなぁと思ったのでメモ。


最近PHPからJavaに移って、複合主キーを使うようになった。
PHPのときはO/Rマッパーが複合主キーに対応ていなかったので選択肢はなかったんだけど、GETやPOSTのパラメーターでキーを沢山並べるやり方は無いなと思ってそのままやってきた。


JavaだとWicketS2JDBCを使っているわけだが、複合主キーを使っていてもめんどくさく感じることがない。
だぶんWicketのおかげ。Wicketだとフォーム処理でIDパラメーターを渡さないからね。
それでもサロゲートキーの方が多くて、どういう分け方だろうと考えたらブコメやトラバに分かりやすく書いてあった。

koyhoge db, sql マッピングを表現するテーブルでは積極的に複合キーを使うなぁ。そこにサロゲートキーを作るのはかえって分かりにくい。 2011/07/14

http://b.hatena.ne.jp/koyhoge/20110714#bookmark-50842882

ただし連関エンティティに関しては、hoge_id + fuga_id みたいなID+IDという複合主キーはそれで十分で、そこにわざわざサロゲートキーを付加するこたぁないっていうかむしろ分かりにくいだろう派

http://d.hatena.ne.jp/akitsukada/20110714/1310670491

例えば商品にタグを付ける場合は

+------+   +------+   +------+
|商品ID|---|商品ID|---|タグID|
+------+   |タグID|   +------+
|・・・|   +------+   |タグ名|
                      +------+

こんな感じだろうか。この場合、商品IDかタグIDで検索をかけることは頻繁にあっても、複合主キーで検索することはあまりない。
ここで「商品タグID」を導入するメリットが思い付かないし、タグを付けたり外したりするたびに連番が消費されるのも精神的に嫌だ。


他にはこんなのもあった。

+------+   +------+
|ログID|---|ログID|
+------+   |種類  |
|時刻  |   +------+
+------+   |データ|
           +------+

概要テーブルと詳細テーブルに分かれていて、取得するときはほとんどの場合概要テーブルとセットで詳細テーブルを呼び出すだろうっていう場合。これが注文情報+注文詳細情報とかになると話は変わってくるが、この場合はログ種類IDを付けたとしても使うことがないかなと。



で、マッピングのためのデーブルは全部複合主キーになっているかというとそういうわけでもなかった。
マッピングマッピング、とかになると主キーがどんどん増えていく。特に意識していなかったが目の前にある図を眺めていると、どうやら複合主キーが三つ以上のテーブルを他から参照するとサロゲートキーを作るという自分ルールが無意識的にあったようだ。
この辺はちょっと頭の隅に嫌な予感が漂うのでもう一度考えた方がいいのかも。





それから、話はずれるが業務的に一意な項目を主キーにするかどうか。
メールアドレスは変更可なので一意だが主キーではない、とするとログインIDは?ログインIDを変更可にするか変更不可にするかで変わるのかな。曖昧な場合はサロゲートキーが無難か。
あと業務的な○○コードとかいうやつ。これは主キーにして大丈夫か?と疑問を持ちつつ主キーにしていたようだ。半年前の自分怖い。
これはコード決定権は誰か、ということに依存するように思う。コードの仕様自体を開発者が決められるのなら主キーでいいような気がする。

また、会員ステータスコードナチュラルキーでしょうか? この場合、コード値自体は業務ではあまり意識しません。会員ステータスのナチュラルキーは、本来は会員ステータス名称であって、 その代理をするキーが会員ステータスコード、つまり、サロゲートキーとも捉えることもできます。その場合は、連番ではないサロゲートキーです。 でも、ちょっと会員ステータスコードサロゲートキーと呼ぶのには抵抗がある感じです。 結局は基準をどこに置くかによってナチュラルキーとも呼べるし、サロゲートキーとも呼べるということかも知れません。 ちなみに、ExampleDB の会員ステータスでは、会員ステータスIDではなく会員ステータスコードという char(3) の人が見て直感的にわかりやすいコード値にしています。コード値の中身の構成変更はほとんど発生しないため、サロゲートキー利用の若干の弊害 "IDだらけ" そして、"結合しないと参照してるものが何なのかわからない" という問題を軽減するようにしています。

http://dbflute.sandbox.seasar.org/ja/manual/topic/dbdesign/surrogatekey.html

会員ステータスコードを会員証に印刷するなら桁数変更などを考慮して主キーにはしない、会員証に印刷するのは会員ステータス名だけだという場合には主キー可、という感じだろうか。しかし後からその仕組み自体が変わる場合を…などと考えると終わらない。難しい。