質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.80%

「メタデータテーブル」という設計 / 考え方について、ご意見をお聞きしたいです

受付中

回答 3

投稿

  • 評価
  • クリップ 4
  • VIEW 11K+

score 32

メタデータテーブルの実用性について最近考えており、皆様のご意見をお聞きしたいです。お気軽にご意見下さい!!

「メタデータテーブル」が正しい呼称かもわからないのですが、下記のようなテーブルの設計のことを指しています。

+++++ 質問したいことについて +++++
■ メタデータテーブル
イメージ説明(wordpressのテーブルです)

usersテーブルではログインや、最低限必要な情報のみを保持しています。
usermetaでは、userの拡張情報を格納します。例えば、IDが1のユーザーの住所は、usermeta内で、
umeta_id:(AUTO_INCREMEMT),
user_id: 1,
meta_key: address,
meta_value: "東京都品川区住所1-2-3"
のように1レコードとして保持されます。


■ 対して、通常の?テーブル
イメージ説明userに持たせたい情報単位で、カラムを作成しています。


+++++ お聞きしたいこと +++++
上記のような設計を採用した際のメリット・デメリットはどのようなことが挙げられますでしょうか?


私個人、CakePHP等を利用してWebアプリケーションを幾つか立ち上げてきたのですが、毎回同じようなモデル(User, Admin, Post 等)を作っていました。上記設計手法であれば、Model・Controllerの再利用がかなりやりやすくなるのではないかと考えており、次のプロジェクトでは一度採用してみようと思っています。

また、上記設計によってnull許可のカラムが多く存在してしまうことを防げることもメリットなのかなぁ...と。。(住所が入力されていない場合、meta_key: address のレコードを作成しないような制御をとる)


問題点としては、meta_value列への検索クエリが遅くなることが予想されますが、実際どのくらい差分があるものなのだろうかと、疑問に思っています。
meta_keyは、usermetaテーブルのmeta_key と user_id にしっかりとindexを貼っておけば、それほどの差は出ないのではないかと考えております。
あとは、Validateion系は完全にアプリケーション側の責任になってしまいますね。。。


最近Wordpressをゴリゴリいじる機会があって、こういう設計もアリだなぁと。。。
Wordpressは、プラグインフレンドリーを優先して考えて、そうなっているのでしょうね。
だとすると、Web開発フレームワークとの相性も良いはず?!なんて考えています。



ご意見いただければ幸いです!
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+5

いわゆるEntity-Attribute-Valueと呼ばれるSQLアンチパターンですね。

デメリットを認識してそれでも採用するのなら構わないと思いますが…(自分も使うことはあります)。

ただ今回の場合は、メタデータテーブルを作らなくても、例えばusersテーブルのaddressだけをオプショナルにしたいのなら、users_adressテーブル的なものを作ってuser_idでusersテーブルと1:1で紐付ければ良いのではないかなと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/28 01:12

    有難うございます!アンチパターンの一つとして挙げられていたんですね。

    確かに、ある1つの大きなシステムの設計(例えば、金融系の基幹など)だと、ありえないと思います。クエリの投げ方が複雑になるのと、Validationの部分が、問題視されているようですね。

    参考のためにお聞かせ願いたいのですが、EAVパターンを採用される場合はどのような状況でしょうか?

    キャンセル

  • 2015/06/28 09:00

    社内で開発したCMSがあって、そのカスタム値を格納するためにEAVパターンを使いました。そのCMSは多数のサイトで使っているので元のテーブルの構造を変えるわけにはいかず、しかし各サイトによって独自に拡張する可能性がある場合ですね。

    キャンセル

+4

私的には、あまりお勧めができない設計かと思います。

デメリットとして、以下のようなものが考えられます。
(SQLアンチパターンの5章 EAVからの受け売りですが…)

1. データの整合性を担保できない
質問内容に記載されていますが、validationがアプリケーション任せになります。
いくらアプリケーションで注意深くプログラムを作っても、不整合を起こしたデータが紛れ込まないとは言い切れません。(アプリケーション側でもvalidationチェックをすること前提としても)

not null制約をつけれない
→必須項目がないデータが入る可能性

データ型を指定できない(meta_value列はおそらく、文字列で格納すると思うので)
→日付項目に日付変換不能データ、数値項目に数値変換不能データが入る可能性

外部キーを使えない
→他のテーブルとのデータ整合性を強制できない

属性名を管理しなければいけない
meta_key列に入力できる属性値は、どこで管理する?従来ならカラム名として名前は強制されていたもの。

2. SQLを構築するの面倒
ユーザの情報をすべて取得するときは、大変だと思います。
userテーブルをselectした後、そのidをもとに、usermetaテーブルに再度selectすると
1回でよかったsql発行が2回になってしまいますし。また取得したデータをループで回してプログラムで1ユーザを1行のデータとして再構築しなければいけません。

selectを一回で済ませたいなら
select i.*
      ,i1.meta_value as address
      ,i2.meta_value as mail
・・・・
  from user i
left outer join usermeta i1
  on i.id = i1.id and i1.meta_key = 'address'
left outer join usermeta i2
  on i.id = i2.id and i2.meta_key = 'mail'
・・・・・
とかいうsqlになります。

メリットは、すいません思いつかないです。
あえて言うなら、柔軟に属性値をふやせるということでしょうか。
でも上記のデメリットを許容してまでのメリットかどうかは…


毎回同じようなモデル(User, Admin, Post 等)を作っていました。上記設計手法であれば、Model・Controllerの再利用がかなりやりやすくなるのではないかと考えており

おそらく、User,Admin,Postのユーザ情報を格納して、同じような項目が複数のテーブルに出てくるのが嫌ということでしょうか?

それでしたら、ユーザ情報で共通しているものをuserテーブルに切り出して、そのユーザ区分で異なる情報だけを切り出したテーブルmember,administrater,contributorとかのテーブルを作ればいいのでないでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/28 01:20 編集

    やはり、普通に考えて不自然な設計で、本来享受できる機能・メリットが使えなくなってしまうということですよね。その点、激しく同意しております。。(もともと、そのような設計方法を取っておりました)

    恐らくfuzzyをどこまで許容できるシステムかどうか、に依存するかと思うのですが、Wordpressを見て、論理的にどうあるべきかということと、実装として(外部から利用される者として)どうか、ということと少し乖離があるのかなと思いその点で悩んでおりました。

    書いて頂いてやっと気づいたのですが、データ型を指定できないのは致命的ですね。。。order by 句系、検索系でしんどい思いをするのがなんとなく見えてきました...
    ご回答ありがとうございます。

    >属性名を管理しなければいけない
    >→meta_key列に入力できる属性値は、どこで管理する?従来ならカラム名として名前は
    >強制されていたもの。
    これが、かなり厳しい問題なのかもしれませんね。。。打ち間違いでもすんなり保存されてしまいますもんね。

    キャンセル

+2

パッケージ製品で、入力項目を動的に増やしたり減らしたりしたい場合、メタデータテーブル?のような設計になっている事はありました。

メタデータテーブルのような設計にすれば、動的に入力項目を増やす必要がない場合でも、設計変更などで後々、入力項目を追加するケースが発生したとしても、項目定義のマスタデータ投入だけで対応できます。

上記のような利点がありますが、個人的にはメタデータテーブルのような設計は入力項目を動的に増やしたい場合など、必要不可欠な場合以外はするべきでないと思います。

理由としてはシステム開発を行っていると、汎用性などを追い求める事があると思いますが、過剰な汎用性は内部を複雑にし、往々にして開発の失敗要因になる事があるからです。

私個人としては、「必要な物を必要なだけ、できるだけシンプルに」というような方針で設計を行った方がいいのではないかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/28 01:37 編集

    コメントありがとうございます!
    >設計変更などで後々、入力項目を追加するケースが発生したとしても、項目定義のマスタデータ投入だけで対応できます。
    考えるきっかけになったのは、この一文の表すところです。
    naga3 さんと re-24 さんに書いていただいたとおり、型が常に文字列型にならざるを得ないところが明確なデメリットですが、、、わりとどうでもいい属性:プログラム動作上必須でなく、まさにEntity attribute value なものに関しては、こんな設計もアリなのかなぁという想いがまだぬぐいきれず、、

    シンプルにしたいのは山々なのですが、転用したいのも山々でして、その時に、コアとなるuserテーブルのカラムが決まっていると楽、ということもあるかなぁと考えております。


    そして皆様のご意見をお聞きして、更に悶々となっている次第です。

    そのシステムにとっては、逐一カラムをちゃんと定義してあげるのがベスト、ということは私も激しく同意なのですが・・・、わがままで恐縮なのですが、できれば明らかなデメリットや、苦労談が知りたいです!

    キャンセル

  • 2015/06/28 16:11

    デメリットとしては、初めて採用しようとした時、明らかに工数は増えますよね。それがデメリットかと。

    一つのプロジェクトで採用して、それをテンプレート的に使ってやれば、仕様が明確化されていないようなアジャイル開発とかでは有用性はあると思います。ただ一般的な開発手法ではないので、都度開発メンバーに周知は必要かと思います。

    苦労談について、動的に入力項目を増やすとかという事に関連してはないです。
    本件と同じケースだとは思いませんが、必須でないものをこだわりをもって追及していくというのは、地獄をみるような失敗プロジェクトの要因の一つであるという個人的な経験による所感があります。おれおれフレームワーク的な設計はできれば避けた方がいいかと。。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る