同じカラム名に連番をつける設計がなぜダメなのか
同じカラム名に連番をつける設計がなぜダメなのか
私はこれまで *_1, *_2, *_3 のように 同じカラム名に連番を付ける設計を自分でやったことはありません。
しかし現場のスキーマに目を通すと、このパターンを見かけます。
最初は「手っ取り早い」と思われがちですが、これは典型的なアンチパターンです。
この記事では、なぜこの設計が問題なのかを整理したいと思います。
なぜ連番カラム設計がダメなのか
1. 第一正規形(1NF)の違反
第一正規形(1NF)は、関係データベース設計の最も基本的なルールです。わかりやすく言うと、 「1つのセルに複数の情報を詰め込んではいけない」「同じ意味のカラムを複数作ってはいけない」 ということです。
たとえば、生徒が複数の電話番号を持つときに、以下のようにカラムを並べてしまうと1NF違反になります。
phone1 | phone2 | phone3
これは「同じ情報を繰り返している」「セルに複数の番号を入れている」と見なされます。
代わりに、「1列に1つの値」として、電話番号は別テーブルに行で持たせるのが正しい設計です。
- 各セルに単一の値だけを格納
- 各カラムには同じ型の値だけを扱う
- 繰り返しグループ(同じ意味の複数カラム)を使わない
といった構造が1NFの要件です。
この基本ルールを破ることは、可読性・拡張性・整合性すべてを損ないます。
📖 参考:
- GeeksforGeeks: First Normal Form (1NF)
- FreeCodeCamp: Normal Forms 1NF 2NF 3NF Table Examples
- Wikipedia: First normal form (1NF)
2. 拡張性の欠如
値を増やすたびに新しいカラム追加が必要になるため、要件変更に極めて弱い設計です。
3. クエリが複雑で非効率
OR や複数カラム検索になり、インデックスが効きづらくパフォーマンスも低下します。
4. データ整合性の問題
value_2 に対応する unit_2 が NULL などの矛盾を防ぎづらい構造です。
5. コードの冗長化
Railsでも同じ処理を複数記述する必要があり、DRY原則に反します。
6. テストケースの爆発
組み合わせが指数的に増え、テストが追いつかなくなります。
子テーブルによる対応 — 1対多
繰り返し属性を正しく扱う方法として最も一般的なのが、子テーブルを使って "1対多" を表現する方法です。
students
id | name | ...
phone_numbers
id | student_id | number
これにより、電話番号はいくつでも追加可能になり、拡張性・整合性・検索性能すべてが改善します。
これはまさに 1NFで求められる設計 です。
中間テーブル(結合テーブル)による対応 — 多対多
実務では 多対多 の関係に正規化すべきケースも多くあります。
例:商品とカテゴリーの関係
商品が複数のカテゴリーに属し、カテゴリーも複数の商品を持つ場合、
category_1, category_2, category_3 のようにカラムを並べるのは典型的なアンチパターンです。
正しい設計は、中間テーブルを導入することです。
products
id | name | ...
categories
id | name | ...
product_categories(中間テーブル)
product_id | category_id
これにより
- 商品は任意個のカテゴリーを持てる
- カテゴリーも任意個の商品に属せる
- クエリや制約もシンプルに書ける
例外的に許されるケース
もちろん、現場では「理想論」だけでは回らないケースもあります。以下のような状況では連番カラムも例外的に許されます。
1. 外部システムとの互換性が必須
既存の外部システムやファイルフォーマットが value_1, value_2, value_3 のような形で固定されている場合。
内部的には正規化し、互換ビュー や シリアライザ を使って「外向きの形式」を連番カラム風に変換するのがベターです。
-
互換ビュー (Compatibility View)
→ 旧構造を再現するSQLビュー。アプリや外部APIからは「昔と同じ形」に見える。 -
シリアライザで連番形式
→ Rails のシリアライザでvalue_1, value_2, value_3というキーを組み立て、外部APIに互換形式を返す方法。
2. 固定カラム数が保証されている場合
「四半期ごとの値を必ず4つだけ持つ」「A1〜C4のステージが絶対に増えない」など、ドメイン的に上限が閉じているケースです。
この場合はワイド表での読みやすさが勝つ場合もあります。
3. 集計専用のマテリアライズドビューやデータマート
データマート (Data Mart) とは、全社的なデータウェアハウス(DWH)の中から特定部門や用途に必要なデータだけを抽出・加工した小規模なデータベースのことです。
営業用、経理用、マーケティング用などに切り出され、分析・BI専用に最適化されています。
- 更新はほとんどなく、読み取り専用
- 正規化よりも集計効率を優先
-
ソースオブトゥルースではなく派生物 として扱う
-
ソースオブトゥルース (Source of Truth)
→ 正しい・唯一のデータを保持するテーブル。原則ここは正規化する。
-
ソースオブトゥルース (Source of Truth)
このような場面では「連番カラムのワイド表」で持たせるほうが集計や可視化に便利な場合があります。
例外は「最終手段」
例外は「許される」ことはあっても 常用すべきではありません。
原則は常に「正規化+リレーション」です。
どうしても必要な場合は「最終手段」としてチーム合意の上で使い、設計意図を必ずドキュメント化してください。
まとめ
- 連番カラム設計は原則アンチパターン
- 1対多 は子テーブル、多対多 は中間テーブルで対応
- ソースオブトゥルースは正規化したテーブルに置く
- 互換ビューやシリアライザは「外向けの見せ方」であり本体ではない
- データマートは分析用の派生物であり、本体ではない
- 例外は「最終手段」。安易に使わないこと
👉 結論: 原則は連番カラムを避ける。例外を使うときは「最終手段」であることを明確にする。
Discussion