BBH
-Biz Branding Hub-
投稿日 : 
2020/07/20
更新日 : 
2020/07/20

【DB設計】そのID列は本当に必要か?テーブルにとりあえずIDカラムを作ってはいけない。

テーブルの多くは、idだったり、xx_idのようなID列を持っていることが多いです。
そのようなテーブルが多いため、「テーブル=ID列を持たないといけない」という勘違いをしてしまうこともあります。
今回は、テーブルに必ずID列が必要ではないということ、ID列を振ってしまったことによって厄介事が起きてしまう事例を見ていきます。

とりあえずID列を振ることによる弊害

とりあえずID列を振ることによって、レコードとしては一意であるが、内容が重複するという事態が発生することがあります。
これは、交差テーブルにID列を振った時に起こります。

例えば以下のように、記事のIDとタグのIDの関連を持つ交差テーブルが存在するとしましょう。
とりあえずID列を振る

交差テーブルの主キーはID列とします。
つまり、交差テーブルはID列さえ重複しなければ、どんなデータでも入力可能です。
例えば以下のようなデータも可能です。
とりあえずID列を振る

これは、IDは異なりますが、内容は全て同じです。
DBのルールには沿っていますが、現実のルールには沿っていません。
同じ内容のデータは1件あれば十分なはずです。

この問題は、DBの状態が気持ち悪いだけにとどまりません。
例えば、あるタグが紐づけられている記事数を調べたい時に問題が発生します。
先のテーブルの例だと、タグ1は記事1にしか紐づいていないはずなのに、重複データのせいで7件の該当行がSELECTされてしまいます。
DISTINCTすれば重複を削除できますが、データが重複していなければそもそもそんな操作は不要です。

これが、とりあえずID列を振ることによる弊害の例になります。

問題の原因は主キーと疑似キーの混同

では、なぜこのような事態が起こってしまうのでしょうか。
それは、主キー疑似キーを混同しているためです。

主キーとは、レコードを一意に特定することができる値です。
テーブル中でその列の値は必ず一意にならなければいけません。

疑似キーとは、主キーの一種です。
これは、テーブル中に主キーとなり得る列が存在しない時に、便宜的に行を一意に特定するために付与するキーです。
また、テーブル中の主キーとなる得る列のことを自然キーと言います。

疑似キーとは、自然キーが存在しない時にやむを得ず付与するものです。
とりあえずIDを付与する行為は、自然キーがあるかないかに関わらず、とにかく疑似キーを付与してしまう行為です。
これにより問題が発生してしまうのです。

例えば、先ほどの記事タグ関連テーブルであれば、わざわざ疑似キーを用意しなくても、記事IDとタグIDを複合主キーとすれば、常に一つの関連が一つしか登録されないように制約を設けることができます。

アンチパターンを用いても良い例

ただし、以下のような場合には自然キーを無視して疑似キーを振ってもよい場合があります。
・ORMフレームワークなどでI要求されている場合
・主キーが物理的に長く、インデックスの作成が効率的でない場合

キー名はスキーマ内で一意になるべき

少し話がそれますが、キー名はスキーマ内で一意になるべきです。
記事テーブルであれば記事ID、タグテーブルであればタグIDが主キーとなります。
単純にIDとしてはいけません。

テーブル内で一意であれば、識別は可能なように思えます。
しかし、テーブルはスキーマ間で参照される可能性があります。
そうした場合に、スキーマ間で重複した名前があると、それのキーがどのテーブルを参照しているのかが名前だけで判別ができません。

テーブルがスキーマ間の参照関係を前提としている以上、キー名はスキーマ間で一意となるべきなのです。

Profile

管理人プロフィール

都内でITエンジニアをやってます。
変遷:中規模SES→独立系SIer→Webサービス内製開発
使用技術はその時々でバラバラですが、C#、AWSが長いです。
どちらかと言うとバックエンドより開発が多かったです。
顧客との折衝や要件定義、マネジメント(10名弱程度)の経験あり。
最近はJava+SpringBootがメイン。

Recommend