DoorKeeper
http://sqlap.doorkeeper.jp/events/4507
以下の書籍をターゲットとした読書会なのです。
![]() | SQLアンチパターン (2013/01/26) Bill Karwin 商品詳細を見る |
場所はいつもの湯島、アルティネットさんです。
参加者は10名かな。初参加1名です。新しい風が入るのは良いですね。
『SQLアンチパターン』読書会、本日は「5章 EAV(エンティティ・アトリビュート・バリュー)」を議論します。 E・A・V! E・A・V! #sqlap
— Takuto Wada (@t_wada) June 27, 2013
今日も相変わらず頼もしい!
ちなみに @t_wada さんがこの書籍を翻訳しようと思ったキッカケは、このEAVだったそうです。
そういう意味でも、非常に興味深い章ですね。
■アジェンダ
by @grimrose さん
今回は @grimrose さんがアジェンダ資料を作成し説明してくださいました。感謝。
テーブル継承をサポートしているORMの紹介など、本に無い部分まで紹介されているのが良いですね。
あと、その前の自己紹介の場で @t_wada さんより書籍の紹介がありました。
■エンタープライズ アプリケーションアーキテクチャパターン
・通称:PofEAA
・@t_wada さんの机にあったはずだが、見当たらなかったので持ってこれなかったとのこと。
・5章のEAVネタは、この書籍に登場するらしい。
![]() | エンタープライズ アプリケーションアーキテクチャパターン (Object Oriented Selection) (2005/04/21) マーチン・ファウラー 商品詳細を見る |
■ディスカッション
今回も議論したいネタを全員で付箋に書き出し、グルーピングしました。

以下、個人メモ。
■EAVでよくある3パターン
(1) カタログデータベース問題
(2) アンケートフォーム問題
(3) コードテーブル問題
■(1) カタログデータベース問題
・製品の仕様を表す各項目は、製品毎に異なる。
・これを製品数分だけ別テーブルとして作成すると、テーブル数が膨大になる。
・この欠点を回避するためにEAVを採用することがある。
■(2) アンケートフォーム問題
・アンケート項目は、アンケート毎に異なる。
・更に、エンドユーザがアンケート項目を決めれるようにすることがある。
(例:DoorKeeperのアンケートフォーム。あとRedmineの項目やナレッジデータベース等も該当する)
・以上より、アンケート項目は自由度が高いため、そもそも最初に項目を決め切れない。
・何が入ってくるかよくわからない、という前提がある。
・これらを踏まえてEAVを採用することがある。
■(3) コードテーブル問題
・いろんなコードデータを1テーブルに突っ込むような汎用設計にする。
(例: [男性 = 1 , 女性 = 2] みたいな、コードと値のペアが多数登録されている状態)
・この設計の意図は、「テーブル数を減らしたい」という点にある。
・例えば、1つのテーブルにいろんなアプリを繋ぎたい場合に採用する。
・利点: DBでコードを一括管理できる。
■EAVを使うかの判断
・バリエーションが有限なら、5.5節のテーブル継承でやりましょう。
・たとえ12種くらいあっても、よく似ている12種類なら継承で表せるかも、と考える。
・バリエーションが20未満くらいなら、サブタイプ(テーブル継承)で行くべき。
・テーブル継承にはやり方が3つある。
①シングルテーブル継承(略称: STI)
②具象テーブル継承
③クラステーブル継承(略称: CTI)
■@t_wadaさんのテーブル継承レクチャー
・上で挙げた書籍 PofEAA に関するWebサイトの題材を使って、@t_wada さんがホワイトボードでレクチャーしてくださいました。感謝!
http://martinfowler.com/eaaCatalog/singleTableInheritance.html
・[題材]: スポーツ選手のDBを作りましょう。
- Footballer
- Cricketer
- Bowler
- etc
・このテーブル設計の方法がわからなくて、EAVでやりがちなのは以下の設計。
(1)まず Playerテーブルを作る。カラムは以下2つ。
①id
②name
(2) 次に、EAV用に PlayerArgsテーブルを作る。カラムは以下3つ。
①id (Playerテーブルへの外部キー)
②attrname(キー)
③attrvalue(バリュー)
・でも、この程度ならEAVを使うべきではない。解決策として以下3種のテーブル継承を使う。
【1】シングルテーブル継承(STI)
・PofEAA: Single Table Inheritance
http://martinfowler.com/eaaCatalog/singleTableInheritance.html
・要するに、全部入りテーブル。
・type列に、"Footballer"とか判別タイプが入っている。
・typeの扱い方と、共通しない列にnullが入ることを受け入れられるのなら、使える設計。
・ORMはデフォルトでSTIを採用していることが多い。
・ただ、nullが多くてスカスカになる。密度が低くなる。
・データの偏りが性能に影響する。Footballerの人数が少なかったら、"Footballer"の検索が遅くなったりとか。
・なので、ちゃんとインデックスを設計しないといけない。
・DBのディスク容量を厳しく管理するプロジェクトは、STIを嫌がることがある。
・具象テーブル継承やCTIよりは、検索は速いことが多い。なぜなら全部入りテーブルなので、Joinが必要なくなるから。
【2】具象テーブル継承
・PofEAA: Concrete Table Inheritance
http://martinfowler.com/eaaCatalog/concreteTableInheritance.html
・Playerテーブルがない。
・絶対に必要なカラムだけテーブルに用意しましょう、という設計。
・nullでスカスカな状態は生まれない。
・でも、nameで検索したい時、全テーブルを検索しないといけない。なので串刺し検索に弱い。
・でも参照整合性とかには強い。
・あと、STIで必要だったtype列が必要がなくなる。
・1人が複数のプレーヤーをこなすマルチプレーヤーも扱える。
・STIだとマルチプレーヤを扱うのは無理。type列で区別すればいけるが、主キーが衝突するので、新しいキーを設計する必要が出てくる。
【3】クラステーブル継承(CTI)
・PofEAA: http://martinfowler.com/eaaCatalog/classTableInheritance.html
・要するに、差分だけ各テーブルに持たせる設計。
・CTIだと、Bowlersの情報を取得するためには、CricketerテーブルとPlyaerテーブルとjoinしないとダメ。
・ただ、設計に一番柔軟がある。
・でもテーブル数が増える欠点がある。
---↑ ココまで@t_wadaさんのレクチャー ↑---
■どのテーブル継承を採用するかの判断ポイント
・まず、RDBMSは動的項目を扱うのは無理、ということを認識する。
・最初はプロトタイプはSTIで作り初めて、行き詰まったらCTIとかリファクタリングを考える。
・STIはシンプルなので、ORMとかはデフォルトで使えることが多いのでコストが少ない。
・テーブルの継承関係が分かってくるまではSTIで行く。分かってきたらCTIとかにリファクタリングを考える。
■NoSQL
・NoSQLとRDBMSを、アプリ側で切り替えて使い分けるアーキテクチャは有り得る。
・NoSQLはDBの補集合でしかない。どのNoSQLを使うべきか、理解してから使うべき。
・医療関係はRDBMSは辛い。というのも、カルテとかは人によって項目が違うので。
→ 医療機関ではCaché(キャシエ)というDBMSがよく使われる。 http://ja.wikipedia.org/wiki/Cach%C3%A9
・HadoopとかはRDBMSではないが、SQLインタフェースが用意されるようになってきた。
→ データの貯め方はRDBMSではないが、インタフェースはSQLが使える。
■XMLデータベース
・XMLデータをDBに入れる場合も、スキーマを定義すべき。
・XMLをLOBとかで丸ごと突っ込むと、検索時に全文検索エンジンが必要になったりして不便。
・XPathを書けるならXMLデータベースも有り。
■振り返り(KPT)
1~5章が終わった区切りに、今回は振り返りとしてKPTをやりました。

参加者の皆さんがどんなことを考えてこの勉強会に参加してるのか、KPTを読むと伝わってきます。
この試みも良いですね。
★感想:
@t_wada さんのテーブル継承レクチャーは大変分かりやすく、腑に落ちました。
本当にバリエーションがわからないからEAVにせざるを得ない状況なのか、考えることが重要ですね。
3つくらいバリエーションが出てくると、めんどくさいからEAVで全部いれちゃえばいいや、となっちゃいがちですが、そうなるとDBMSの良さが失われてしまいます。
ちなみに参加者のうち、EAVの経験者は2名のみでした。
私もEAVは経験したことはありませんでしたが、今後どっかで十分ハマりそうだなぁ、とは強く感じました。
この設計にいつか出会ったら、「あ、この構造、SQLアンチパターンのEAVだ!」みたいに気付けるといいなぁ。
そういう意味でも、EAVという「名前」を書籍で与えたのは大きいですねー。
最後に参加者の皆様、関係者の皆様ありがとうございましたー
- 関連記事
-
- 『JUnit実践入門』写経・実践会 in 横浜 #8 (最終回) #junitbook に参加しました
- SQLアンチパターン読書会 「EAV(エンティティ・アトリビュート・バリュー)」に参加しました
- 「『レガシーコード改善ガイド』討論・品評会 #1 #lckaizen 」に参加しました