EAV(エンティティ・アトリビュート・バリュー)
複数の目的に使われるカラムを用意する設計です。例えば以下のようなテーブルになっていることです。
属性名 | 値 |
---|---|
年齢 | 32 |
趣味 | ゲーム |
特技 | 野球 |
結論から申しますと、汎用性は高いですが、RDBが本来持っている多くのメリットを損なってしまいます。RDBの責務であるデータを守ることが難しいです。
メリット
この設計ではどのような属性名や値でも保存できます。データベーススキーマも正規化も必要ないので設計時に余計な手間が不要です。(DB設計書などのドキュメントなども最低限で済みます。設計思想の解説書くらいはあった方が良いかもですが。)
デメリット
値を取り出すまで以下の状態はわからない点
- そもそも意図した属性名があるかどうかがわからない。
- その属性名に対して値があるか
- 属性名と値の組み合わせが正しいか。
- 属性名一覧
設計に問題がある。
必須属性(NOT NULL)が設定できてない。
例えば、年齢と言う属性であれば必須にできるかもしれませんが、趣味と言う属性名だと趣味がない人もいるかもしれないので必須にはできません。と言うようにEAVではNOT NULL制約をつけることができません。
データ型が指定できない。
日付、数値、文字など様々なデータ型の値が入ってくる可能性があるので、データ型は指定できません。(例えば、日付とかであれば通常はDATETIME型などで日時の設定で縛るのが普通です。)
データの制約もできない上、データが一定ではないので検索範囲の指定を始めSELECT文でのデータの検索上かなり不利なデータ構造になってしまいます。(EAVパータンのテーブルの検索の設計はほぼ無理でしょう。)
正規化できてないので外部キー制約を強制できない。
同じ意味でも表記違いなどが発生しうる可能性があります。(表記揺れ)、本来で例えば、「都道府県テーブル」と「都道府県ID」で外部キー経由で正規化されていて表記の違う値が入ってくることはないですが同じ意味の値でも表記揺れが発生する可能性があります。
属性名を補う必要がある。
属性名自体もタイポなどで間違った表記などが入ってしまう可能性があります。例えば、年齢という属性名にしたいのに年月みたいな属性名にタイポで誤って入れてしまうことによって後で見た時に何のカラムかどうかわからなくなってしまいます。
EAVの代替
EAVの代替としてJSON型が出てきました。(MySQL5.7、PostgreSQL9.3など)
これならJSONデータをそのままDBに保存できるのでEAVを使うよりはマシになったかと思います。ただ、それでもメリデメがあります。詳しくは下記の記事で解説しています。
この記事へのコメントはありません。