Entity Attribute Value
可変属性をサポートするなどの柔軟な設計を目指したことに起因するアンチパターン。
テーブル設計
Entity Attribute Value(以下EAV)では次のような項目を持ったテーブルが設計される。
名称 | 役割 |
---|---|
Entity | 親テーブルに対応した外部キーを格納 |
Attribute | カラム名に相当する属性名を指定 |
Value | 属性の値 |
Book
book_id |
---|
1 |
BookAttribute
book_id | attr_name | attr_value |
---|---|---|
1 | name | エンジニアになろう |
1 | status | used |
1 | creater | USER1 |
1 | price | 3520 |
1 | page | 450 |
1 | release_date | 2020/9/24 |
1 | review | 3.5 |
1 | size | 5x20x25cm |
メリット
- テーブルの列数を削減できる
- 新規の属性を追加する際に列数を増加しなくて良い
- 属性が存在しない列にNULLが入りNULLだらけのテーブルにならない
- データベースの構造は単純になる
デメリット
- データの取得が冗長化する
- 特定の属性にNOT NULL制約を設定できない
- データ型を使用できない
- 外部制約キーを使用できない
- 動的に属性名が増えるため整合性が担保しづらい
データの取得が冗長化する
Book(EAVを使用していない)
book_id | name | status | creater |
---|---|---|---|
1 | エンジニアになろう | used | USER1 |
BookAttribute(EAVを使用)
book_id | attr_name | attr_value |
---|---|---|
1 | name | エンジニアになろう |
1 | status | used |
1 | creater | USER1 |
「作成者(creater)」を取得したい場合、EAV設計をしない設計では「creater」が存在して入れば1文で必要なデータを取得できるが、EAV設計の場合では「attr_name」で必要なデータを条件として取得する必要がある
特定の属性にNOT NULL制約を設定できない
EAV設計の場合、特定の属性(「attr_name」の「creater」など)に対して個別にNOT NULL制約をつけることができない。
データ型を使用できない
Attribute複数のデータを格納するためデータ型を使用できない。
時間や数値が混在するため文字列として指定することが基本となる。
また同じ日付を格納するにしても「2020−1−1」と登録するパターンや「2020/1/1」と登録するパターンなどが混在しデータの整合性が取りづらい
外部制約キーを使用できない
「attr_name」のうちの1つの属性に対してに外部キーを設定してしまうと全ての属性に制約がかかってしまうため使用できない
動的に属性名が増えるため整合性が担保しづらい
book_id | attr_name | attr_value |
---|---|---|
1 | name | エンジニアになろう |
1 | book_name | エンジニアになろう |
1 | status | used |
1 | creater | USER1 |
属性名が動的に増える可能性があるため整合性が担保しづらい。
上記のように「name」と「book_name」のように同じ本の名称を表す属性が複数登録されてしまうことがあるためあらかじめ属性名を統一して定義しておかないと整合性の担保が難しい。
次回
ポリモーフィック関連