SQLアンチパターン 第三章を読んで
アンチパターン
行の存在の重複をさけるため、主キーを定めることが多くあります。idというカラムを作って主キーの役割をもたせることも多いです。
今回のアンチパターンは全てのテーブルはidというカラムを持たせる、というものです。Railsなんかでもデフォルトではidつけますね。
idカラムの特徴は
- 数字が入ります(正確に言うと32bit or 64bitの整数)
- 同じ数字が入ることはありません
当たり前だと思っていたidもアンチパターンになることがあります。
デメリット
- 冗長なキーができてしまう
ポケモンでテーブルを作成すると
id | pokemon_name |
---|---|
1 | フシギダネ |
2 | ゼニガメ |
3 | ヒトカゲ |
この場合nameは必ず一意になりますしUNIQUE制約もつけられるのでidカラムは必要なキーとは言えなくなります。
また他のテーブルの主キーの組み合わせのを保存する交差テーブルを作っる時にその組み合わせにidをふっても組み合わせの一意にはならないので、組み合わせ2つのカラムにUNIQUEをつける必要がありますがそうなるとidカラムの意味は…ということになります。
- idという名前はかならずしもわかりやすくない idよりpokemon_nameのほうがわかりやすいです。
- USINGが使用できない カラムにpokemon_nameを持ってる例えばTrainersテーブルではUSING(pokemon_name)と使えますが全てのテーブルの主キーがidだとTrainersもidがあるのでusingにidが使えません。
使用してもいい場合
ORMフレームワーク(Ruby on Rails等)では設定より規約ということで、idという整数の疑似キーのカラムがある前提で便利な機能がついています。レールから外れるとその分大変です。ですが疑似キーをid以外の名前(pokemon_idとか)にすることもできることは覚えておいたほうが良さそうです。
Railsも主キーを変更することは公式でサポートされています。
https://railsguides.jp/active_record_migrations.html
解決策
状況に応じて適切に調整しようとあります。そりゃそうだという気持ちになったのは私だけでしょうか。
- 主キーをわかりやすい名前にする
idをproduct_idにするとかですね
- 自然キー、複合キーの活用
例のpokemon_nameのように自然に主キーとして使えるものもあるでしょう。こういった自然キーがない、もしくは将来的に信用できない時に擬似キーを使うべきです。 複合キーもカラムの組み合わせが行を識別する時に最適というときには使うといいでしょう。
感想
規約は必要不可欠というわけではない、柔軟に対応しようねといった章だと思いました。 idというカラムを主キーにすることが悪というよりはそれ以外の主キーの設定もあると知らないのが悪という感じですね。そもそも主キーが連番である必要もデータ型である必要もないというのをデータベース実践技術入門で読んだことがあります。