はじめに
今までDBのテーブル設計をする際、業務や個人の学習としてサービスを作成しDBを見て触っていたため、なんとなくこういう設計をすればいいんだという曖昧な知識はあった。
個人の学習としてサービスを作成した際にもそこまで複雑な設計ではなかったため問題なく動くものは作れていた。
ただ、改めて「DBの設計についてちゃんと勉強したことないなぁ....」と思い勉強をしてみることに。
現状、最低限の設計については抑えているつもりではいるので、今回はSQLアンチパターンに焦点を当てて学習をしてみる。
ジェイウォーク(信号無視)
今回はジェイウォーク(信号無視)について。
ジェイウォークとは、1つの列に複数の値を格納するアンチパターン。
以下のようなパターンが当てはまる。
question
id | question | choice |
---|---|---|
1 | 問題文1 | 選択肢1,選択肢2,選択肢3 |
2 | 問題文2 | 選択肢4,選択肢5 |
3 | 問題文3 | 選択肢6,選択肢7,選択肢8 |
ジェイウォークのデメリット
ジェイウォークを使用することで以下のようなデメリットが発生。
- 特定の値を持つ行の検索時にパターンマッチが必要になる。
- データの更新、削除がしづらい。
- 外部キーを結合していた場合に意図した結果が取得できない。
- 集約クエリの作成ができない。
- 投入データの妥当性が担保されない。
- インデックスのメリットがない。
- データが増えることによる格納制限。
上記で挙げたようなデメリットが発生。
検索時にLIKE演算子が必要、更新には文字列の連結が必要でソートに対応しない、削除には元の値を取得して新しい値を保存、文字列として扱うため数値を扱いたい場合でも意図しない文字列が混入する可能性がある.....etc
解決策
交差テーブル(中間テーブル)を作成する
言わずもがなだが。
これを踏まえて先ほどのテーブルを再度見てみる。
choice列のデータがジェイウォークに該当する。
question
id | question | choice |
---|---|---|
1 | 問題文1 | 選択肢1,選択肢2,選択肢3 |
2 | 問題文2 | 選択肢4,選択肢5 |
3 | 問題文3 | 選択肢6,選択肢7,選択肢8 |
これを修正すると以下のような構成になる。
question
id | question |
---|---|
1 | 問題文1 |
2 | 問題文2 |
3 | 問題文3 |
choice
id | choice |
---|---|
1 | 選択肢1 |
2 | 選択肢2 |
3 | 問題文3 |
4 | 問題文4 |
... | ... |
question_choices
id | question_id | choice_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 3 |
4 | 2 | 4 |
... | ... | ... |
これで解決。
まとめ
- 値は結合して格納せずひとつずつ列、行に格納した方が良い。
次回
ナイーブツリー (素朴な木)