【SQLアンチパターン】EAV(エンティティ・アトリビュート・バリュー)について
こんにちは、CryptoGamesの高橋です。
ブロックチェーンサービスを行っている会社です。
今回は「SQLアンチパターン」の第5章の「EAV(エンティティ・アトリビュート・バリュー)」について、見ていきます。
では早速、見ていきましょう。
0 前提条件
下のように、「問題」に関する情報を管理したいとします。
しかし、「問題」にはいろんな種類があり、テーブルの列に入れる内容がさまざまになりそうです。
また、問題の種類も今後増えるかもしれません。
1 アンチパターン EAV
1ー1 EAVとは
EAVとはEntity Atribute Valueの略です。
Entityが実体、Atributeが属性で、Valueが値なので、属性と値の対応関係を入れていくテーブルになります。
下のようになります。
初見だと分かりにくいですが、例えば1002番には
の属性とその値が入っています。
このように、どのような属性を入れるかも指定することができます。
そのため、「クレーム」に特有な「重要度」列や「要望」に特有な「スポンサー」列を作ることができます。
1ー2 欠点① 特定の属性を必須にできない
仮に「報告者」の属性はどの問題番号でも必須にしたいとします。
しかし、その手段がないので、下のように「1002」番には「報告者」が漏れています。
1ー3 欠点② フォーマットの統一が困難
自由に入力ができてしまうので、フォーマットの統一も困難です。
例えば、下のように、日付の統一が困難になります。
1ー4 欠点③ 属性名の統一が困難
下のように、同じ意図と思われるものが「報告日」と「報告日時」で二つできてしまっています。
自由に入力ができてしまうために、このような属性名の統一も困難です。
1ー5 欠点④ 外部キー制約ができない
下のように、「ステータス」で外部キー制約を行いたいものの、自由に入力ができるため、制約することができません。
1ー6 欠点⑤ 同一の問題番号の属性を取るために、処理が必要
一般的なテーブルの場合、右のような属性の状態はすぐに出せます。
しかし、EAVの場合、全ての属性を連結しないとこの状態を得られません。
2 4つの解決策
本書ではこのEAVに対処するために、4つの解決策が示されていました。
一つ一つ紹介していきます。
3 シングルテーブル継承
3ー1 概要
シングルテーブル継承とは、下のように、考えうる属性を全て列に入れて一つのテーブルにする方法です。
また、どのタイプに所属するかがわかるように「問題タイプ」のような列を入れるのも特徴です。
これなら外部キー制約や問題番号(一行)ごとの内容の取得を容易に行えます。
3ー2 欠点① 新たなタイプを作ると、それに応じた列が必要
下のように、新たなタイプを加えると、新しい列が必要になります。
それに応じて、「-」という、値が不要な行が増えます。
3ー3 欠点② タイプと列が紐づいていない
「問題タイプ」という列を作ったものの、これはどの列と関連づくのかを設定できません。
例えば、上のように、「要望」タイプは「スポンサー」、「スポンサー要望」という列に紐づけたいと思っています。
ただ、その強制ができないので、「問題番号:1005」のように、誤ったタイプに値が入力される可能性があります。
4 具象テーブル継承
4ー1 概要
具象テーブル継承は、下のように、シングルテーブル継承から、タイプごとにテーブルを分けたものです。
これにより、シングルテーブル継承の欠点②「タイプと列が紐づいていない」が解消しました。
また、シングルテーブル継承で「-」となっていた不要な列も無くなりました。
その他、下のように、「問題タイプ」の列も不要になりました。
4ー2 欠点① 共通項目と特有項目の区別がつかない。
欠点の一つ目は、どこまでが共通項目かが明確でないことです。
見た目上は、下のように区別されそうですが、テーブル上は明確に示すことができません。
4ー3 欠点② 共通項目に新たな列を追加する場合
具象テーブル継承は全てのテーブルで共通項目が存在します。
そのため、共通項目に列を追加したい場合、全ての具象テーブルに列を追加する必要があります。
5 クラステーブル継承
5ー1 概要
具象テーブル継承から、さらに共通のテーブルを分離したのがクラステーブル継承です。
下のようになります。
これにより、シングルテーブル継承、具象テーブル継承の欠点が解消できます。
その他、その問題番号の一行を取ってくるのも簡単な操作で実行ができます。
5ー2 欠点(本書には記載なし)
クラステーブル継承の欠点らしい欠点は本書には記載がありませんでした。
私も、基本的には、このクラステーブル継承を使うのが良いのではと思いました。
ただ、サブタイプの種類が多い場合や、頻繁に新しい属性を追加する場合は、次の「半構造化データ」を用いるのが良さそうです。
6 半構造化データ
6ー1 概要
これは考え方がEAVと似ています。
下のように、共通部分は通常の列として格納し、特有部分はテキスト形式で格納する方法です。
これによって、頻繁に属性が加わるなど、クラステーブル継承では大変なケースに対応できます。(頻繁に列を追加するのは大変そうです。)
6ー2 欠点 EAVと大きく被ります。
属性部分をテキストで入れているので、EAVと同じ問題が起こってきます。
例えば、フォーマットや属性名の統一は困難ですし、外部キー制約もできません。
それらの欠点以上のメリットがあるケースで使用することになりそうです。
7 最後に
いかがだったでしょうか。
私は「クラステーブル継承」が良いと思いました。
それを納得するためにも、「シングルテーブル継承」、「具象テーブル継承」などのメリット・デメリットを押さえるのが良いとおもいました。
以上です。
サポートをしていただけたらすごく嬉しいです😄 いただけたサポートを励みに、これからもコツコツ頑張っていきます😊