- PR -

主キーにブランクの可能性がある項目はありですか?

投稿者投稿内容
ZIEK
会議室デビュー日: 2005/09/10
投稿数: 2
投稿日時: 2005-09-10 17:48
初めて質問させていただきます。

現在、モデリングの作業として、各業務からあがってくるエンティティを
精査して、エンティティとして正しい形なのかを判断している作業を行っております。

その中に、主キーにも関わらず場合によってはブランクが設定される
可能性がある項目を持つエンティティ申請票があがってきました。

【例】
項目A(PK)
項目B(PK)
項目C(PK)
項目D(PK ブランク可能性あり)
項目E(PK ブランク可能性あり)
項目F(PK ブランク可能性あり)

上記のテーブルは、項目A〜Cまでは必須ですがその後ろのD〜Fまでは場合により
設定されるとのこと。つまりD〜Fまででバリエーションが発生するということです。

これを見て私は、D〜Fを主キーから外して単純な連番で一意にすればいいのでは?
と考えました。
その理由として、今回のエンティティには主キーに必ずクラスター索引が
設定されるので、例えばDがブランクでEには値が設定されていた場合、
Dの時点で索引が適用されないのでいかと思ったからです。
また追加時のパフォーマンスも劣化するのでは?と思ったからです。

データベースはDB2を使用しています。

【質問事項】
1.主キーにブランクの可能性のあるエンティティはありですか?
2.その場合の、デメリットはどの程度ですか?
3.対応方法として、連番は正しいやり方でしょうか?

以上3点をできれば回答をお願いいたします。

ささぴん
会議室デビュー日: 2002/07/16
投稿数: 5
投稿日時: 2005-09-10 18:57
すんごくひさしぶりに書き込みます。

業務システムの設計をやっているワケではありません。あくまで趣味でソコソコやっているレベルなのですが、設計ポリシーとして、PKはできるだけシンプルにする方が良いと考えています。

複数のフィールドにより、事実上とか実質上PKが構成できる、としても、それとは別に「コレ一つでレコードがカンタンに取り出せるなぁ」というPKを必ず用意することにしています。その上で個々のフィールドの意味を考えて、PK、UNIQUE、INDEXを使い分ける様にしています。運用やパフォーマンス的に云々という話では無いのですが、関連するコーディング作業がシンプルになって便利かと。

ということで、主キーのフィールドの数を減らす方向に賛成の方向で、

Q1>それ以前に別のフィールドを作ろうと考えます。
Q2>関連したコーディングやメンテが面倒になりそう。
Q3>賛成です。正しいかどうかは判りませんが・・・。

みたいに意見を上げさせて頂きます。如何でしょうか?トンチンカンかも知れませんが。
でっち6号
大ベテラン
会議室デビュー日: 2005/01/31
投稿数: 176
お住まい・勤務地: Kawasaki
投稿日時: 2005-09-10 20:21
こんにちは。
ちょっとDB2には明るくないので、こういった手法もありますよ、と言うのを一点だけ書きます。

私が似たようなデータを格納するテーブル定義を行った際には、各項目データをデリミタ付きで連結して格納するフィールドを一つ用意し、そこを主キーにしました。(各項目用の列も当然あり。)
キー値となる項目に対する更新頻度がほぼ0で、なおかつキー項目による検索頻度とキー以外の列の更新頻度が高かったための処置です。

レコード自体の更新頻度が低く、自然キーでの検索頻度が低い場合は、私も連番などにしてしまいますね。
(主キーのNull許可はどうしても抵抗が...)


[ メッセージ編集済み 編集者: でっち6号 編集日時 2005-09-10 20:36 ]
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2005-09-10 20:35
unibon です。こんにちわ。

引用:

ZIEKさんの書き込み (2005-09-10 17:48) より:
1.主キーにブランクの可能性のあるエンティティはありですか?
2.その場合の、デメリットはどの程度ですか?
3.対応方法として、連番は正しいやり方でしょうか?


今回の場合、主キーがブランクと言うよりも、主キーを構成する列のいくつかがブランク、と言うことになります。これ自体はブランクであっても構わないです。デメリットは別段ないはずです。なお、この段階でインデックスを気にするのは早すぎるかもしれません。DBMSの実装にもよるかもしれません。もっとも先回りして考慮するのは悪くはないですが。

「連番」は、いわゆる人為キーや人工キーと呼ばれるものであり、これは付けても付けなくてもどっちでも良いです。両方が考えられます。
「主キーについて」
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?forum=26&topic=20585
が近い話題かもしれません。
なお、ユニークであれば良いのでかならずしも連続している必要はないので、「連番」は条件を絞りすぎです。もっとも「連番」にすることは多いです。「連番」の中にもさらに抜けを許すか、抜けを許さないか、などのバリエーションはありますが。
ただ、人為キーを付けるか付けないかは、できるだけ現実世界の物事に対応付けて考えたほうがよいです。現実世界ではそういう識別子を付けないのにDB内だけで人為キーを付けると、DB内の管理項目が増えてしまいます。私だったら、数倍のパフォーマンスの向上のために人為キーをつけるよりは、多少遅くても付けなくて済むなら付けないほうを選びます。
現実世界でも、たとえば顧客を識別するのに、氏名と住所と生年月日で足りるけど、普通はあえて「顧客番号」のような感じで人為キーを付けると思います。そういう場面ならDB内でも人為キーを使うのはためらわなくてよいと思います。
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2005-09-10 23:09
引用:

1.主キーにブランクの可能性のあるエンティティはありですか?



ありです。一意になるのであれば別に問題はないと思います。

引用:

2.その場合の、デメリットはどの程度ですか?



とくにないでしょう。

引用:

3.対応方法として、連番は正しいやり方でしょうか?



一意になるのであれば別に連番にする必要はないでしょう。
業務的に正規化を進めるとかいう対処法でないのであれば連番にするのもあまりいいやり方ではありません。

引用:

その理由として、今回のエンティティには主キーに必ずクラスター索引が
設定されるので、例えばDがブランクでEには値が設定されていた場合、
Dの時点で索引が適用されないのでいかと思ったからです。
また追加時のパフォーマンスも劣化するのでは?と思ったからです。



索引を利用するしないにクラスタ化は無関係です。
Dがブランクという条件をつけてやればEの条件で索引は利用されます。
追加時のパフォーマンスも連番の場合と同じです。
ZIEK
会議室デビュー日: 2005/09/10
投稿数: 2
投稿日時: 2005-09-11 22:06
こんばんわ。皆さんご回答ありがとうございます。
どうやら皆さんの意見を聞く限り、主キーにブランクがあったとしても
特に問題はないようですね。

ただどうしても今までの経験上、主キーにブランクがあることに抵抗があったのと、
以前に、同様のケースがありその際にはシーケンスオブジェクトで連番をふる項目を
主キーにしてもらったという経緯があったので、今回もそうするべきという
「べき論」がありました。

ただどうしても不安になったため、自分の意見の裏付け欲しかったために、
ここで皆さんのご意見を聞かせてもらいました。

私の意見はどうも概ね撃沈のようですね。
明日再度担当者に話を聞いて、更新頻度や検索頻度等を調査して検討したいと思います。
貴重なご意見ありがとうございました。
まだ、何かご意見がありましたらどしどし書いてください。
参考にさせていただきます。

結果は後ほどご報告させていただきます。
sophia(rc)
会議室デビュー日: 2005/09/02
投稿数: 18
投稿日時: 2005-09-13 11:46
1.主キーにブランクの可能性のあるエンティティはありですか?
 -> 主キー(候補キー)がブランクを持つというのは、通常のテーブル設計ではありえないです。
2.その場合の、デメリットはどの程度ですか?
 -> 後に示すように、行を正しく一意に識別することができなくなります。
3.対応方法として、連番は正しいやり方でしょうか?
 -> 候補キーの列が多すぎて扱いづらい場合に、代替キーとして UNIQUE な単一列を
  つくることはありだと思います。
   ただ、今回あげられたようなブランクを含む候補キーは候補キーになりえないので、
  必要に応じてテーブルを分割したりして列を整理するとよいかと思います。

 候補キーにブランク(NULL?)があったら候補キーになりえない理由として、たとえば

a|b|c|d|e|f
-+-+-+-+-+-
0|0|0|0| |
0|0|0|0| |
0|0|0| |0|
0|0|1| | |1

といった値が入ったとき、1行目と2行目が競合しているか正しい行かわからなくなりませんか?
「ブランク」が不定値の NULL ではなく " "(空白)などで決まっていれば1行目と2行目は
競合しているといえますが、NULL であれば競合しないことになってしまいます。

ACCESS2000/JET4.0 の場合、PRIMARY KEY 制約を複数列に設定すると自動的に全列
NOT NULL 制約がつけられますので、そもそも d,e,f 列に NULL は入らなくなります。
 代わりに UNIQUE INDEX を使って試してみると、見た目が同じである1行目と2行目を作ることが
できます。しかし、この2行をどうやって識別したらよいのでしょう…?

 その表の詳細がわかりませんが、当方が設計するなら以下のようにします。
表X
 項目A
 項目B
 項目C
 主キー(項目A, 項目B, 項目C)
表Y
 項目A
 項目B
 項目C
 項目コード(D,E,F のどの列の項目かを示す)
 項目DEF
 主キー(項目A, 項目B, 項目C, 項目番号)
 外部キー(項目A, 項目B, 項目C) 参照先->表X(項目A, 項目B, 項目C)

先の表の 2,3,4行目を書き直すと、

a|b|c
-+-+-
0|0|0
0|0|1

a|b|c|コード|def
-+-+-+----+---
0|0|0|  D| 0
0|0|0|  E| 0
0|0|1|  F| 1

といったイメージです。
 この表X,Yの候補キーが長すぎるのをきらって
UNIQUE 制約をつけた代替キー列を作ることは問題ないかと思います。
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2005-09-13 12:42
ZIEKさんの言われているブランクは''のような文字列型をさしていると思います。
そうした場合候補キーにブランクはいくらでもありえると思います。
そもそも関係データベースの定義上の候補キーなんてものは1行全体を候補キーにしてしまってもいいわけですから。

スキルアップ/キャリアアップ(JOB@IT)