データーベース設計段階での質問

このQ&Aのポイント
  • データーベース設計段階での質問です。管理しなければならないフラグ項目が100近くあり、そのフラグがよく検索対象になります。
  • 現在使用中のデータベースでは10個のカラムをつくっていて、対象フラグのIDを列挙しています。他に日付などのカラムも存在します。
  • このままでは検索がややこしくなるため、効率のいいデータベース設計方法を教えてください。
回答を見る
  • ベストアンサー

データーベース設計段階での質問です。

データーベース設計段階での質問です。 管理しなければならないフラグ項目が100近くあり、そのフラグがよく検索対象になります。ただし、1レコードにつけられるフラグは10個までと決まっています。現在使用中のデータベースでは10個のカラムをつくっていて、そこに対象フラグのIDを列挙しています。 例えば A項目に対して1,20,34,56,78 B項目に対して3,6,11,15,42,78,89 のフラグがたっている場合、 name f0  f1  f2  f3  f4  f5  f6  f7  f8  f9 ------------------------------------------------------ A   1   20  34  56  78  null null null null null B   3   6   11  15  42  78  89  null null null となっています。他に日付などのカラムが5項目ほどあります。 このままだと検索等でややこしいことになるため テーブルを整理したいと思っています。 1.100個のboolean型のカラムを作る 2.ビットフラグ(ビットフィールド)のカラムを4つほど作って、検索時ビット演算する 3.項目名(ID)とフラグNo、だけの2カラムで構成した別テーブルを作ってjoinする 4.文字列としてIDを格納し、フルテキストインデックスをはる などがあると思うのですが、効率のいい設計がいまいちよくわかっていません。 上記の方法以外にも何かいい方法があると思います。 このような場合の、テーブル設計の方法を教えて下さい。

質問者が選んだベストアンサー

  • ベストアンサー
  • Saturn5
  • ベストアンサー率45% (2270/4952)
回答No.4

No.3の方が書いておられるように、テーブルに配列が使えればいいですね。 しかし、これはDBエンジンがユーザーに配列のように見せているだけで、 内部は最大フィールドが用意されていて、使わないところにはnullが入って いるように思います。 さて、以前の解答で(1)または(3)の方法が良いと書きました。 フラグが立つ確率が20%以上ならば間違いなく(1)でしょう。 確率が10%以下ならば(3)もコンパクトで速いと思います。 さて、集計ですが、(1)も(3)も同じ事です。 (1)では単純に集計できますし、(3)もIDでグループ化すれば 簡単に集計はできます。

sonyfreak
質問者

お礼

丁寧に解説して下さり、ありがとうございます。テーブル設計でやけに悩んだのは今回が初めてです。Saturn5さんの回答内容を見させていただき、より柔軟に対応できるようにしたいと思いました。割合による目安まで含めて下さり、大変参考&勉強になりました。ありがとうございました。

その他の回答 (3)

  • yamada59
  • ベストアンサー率74% (29/39)
回答No.3

PostgreSQL 以外のデータベースで同じことができるか分からないですが、PostgreSQL には配列型というデータ型があり、それを使うと SQL もすっきりと書ける上にインデックスを使って高速に検索できます。 CREATE TABLE t ( name text, flags integer[] ); SELECT * FROM test LIMIT 5; name | flags ------+-------------------------------- 1 | {18,99,86,79,35,19,40,80} 2 | {96,14,27,38,80,44,16,99,22} 3 | {53,65,84,85,86,90,94} 4 | {3,13,3,97,77,99,29,25,92} 5 | {77,59,56,97,98,63,34,80} (5 rows) CREATE INDEX test_flags_idx ON test USING gin (flags); フラグに 1 かつ 2 を含むデータを検索する場合には、 SELECT * FROM test WHERE flags @> ARRAY[1,2] LIMIT 5; name | flags -------+------------------------------- 90609 | {1,11,39,12,2,32,23,68} 8267 | {86,70,2,33,95,79,94,1,12,15} 15346 | {45,26,81,13,1,14,88,46,15,2} 99014 | {84,58,30,89,97,2,25,95,1} 75943 | {1,1,84,9,64,2,4,9} (5 rows) 1 または 2 を含むデータを検索する場合には、 SELECT * FROM test WHERE flags && ARRAY[1,2] LIMIT 5; name | flags -------+-------------------------------- 45020 | {90,1,3,11,33,72,73} 6 | {2,5,27,5,60,81,54,68} 13 | {2,87,33,26,73,22,19,63,73,21} 74259 | {74,26,86,65,22,25,2,15,50} 9987 | {5,42,1,59,86,7,78,82} (5 rows) といった感じです。

参考URL:
http://www.postgresql.jp/document/9.0/html/functions-array.html
sonyfreak
質問者

お礼

配列型、初めて目にしました。PostgreSQLは使ったことがないのですが少し気になる存在になりました。ただ、SQL99で定められているのにあまり普及してなさそうなのが残念です。DBで標準的に配列型が使えるようになると、今回のようなケースの設計もあれこれ考える手間が減りそうですね。 検討中のDBにPostgreSQLが含まれていないため、今回は少し難しいですが、非常に勉強になりました。ありがとうございました。

  • layy
  • ベストアンサー率23% (292/1222)
回答No.2

検索対象となるテーブルが2次元ということから改善。仕掛けややこしくしていると思います。 1次元テーブルで検索すること考える。 提示してあるテーブルは、1次元テーブルからクロス集計クエリで作成する。 それか、ほかには 縦軸横軸が逆のテーブルも作る、 逆のが別に存在すれば、検索値対象が1項目で100レコードしか存在しない?。

sonyfreak
質問者

お礼

そうですね。2次元なのがおかしいのは重々承知しています。前任者がなぜこのようなテーブル構造にしたのかよくわかりませんが、そのためにテーブルを調整する必要を感じ、質問させていただきました。 逆のテーブルの発想はありませんでした。ありがとうございます。ただ今回のデータの場合、1つのフラグに対して項目が1つだけというわけではありませんので、残念ながら適応できませんでした。別の機会に活用できる知識としていただいておきます。

  • Saturn5
  • ベストアンサー率45% (2270/4952)
回答No.1

1.100個のboolean型のカラムを作る 2.ビットフラグ(ビットフィールド)のカラムを4つほど作って、検索時ビット演算する 3.項目名(ID)とフラグNo、だけの2カラムで構成した別テーブルを作ってjoinする 4.文字列としてIDを格納し、フルテキストインデックスをはる まず、2はダメです。 この仕事を内部でするのがデータベースエンジンであり、これを使うならば1の方法が いいと思います。 4はデータに無駄が多いと思います。 結論としては1または3でしょう。 1の利点はデータベース構成が比較的単純で、最も検索が速いと思われます。 欠点はフィールド数が多いこと、使わないフィールドが多い、事でしょう。 3の利点はデータベース構成が最も単純であること、フィールドの無駄が無いことでしょう。 また、1レコード当たりのアクセスも最も速いと思われます。 ただし、レコード数がフラグ数だけ発生し、検索の度にグループ化をする必要があり、 Indexが効きにくく、検索に時間がかかると思われます。 正規的でコンパクトなデータベースという点では3でしょうが、最近のHDの高速化、 大容量化という状況の変化、かつメンテナンスのしやすさを考えると1の方法が最善では ないかと思います。

sonyfreak
質問者

お礼

正規化にとらわれない柔軟な回答、とても参考になります。ありがとうございました。質問時に忘れていた事なのですが、これらのフラグは検索に使うだけでなく、特定の項目にどのフラグが立っているかという集計もすることがあります。もしこれも踏まえて、テーブル構成に関するアドバイスがさらにあればご回答いただけると非常に助かります。 ベストアンサーにさせていただきたいところですが、もう少し回答を募集してからにしたいと思っています。ありがとうございました。

関連するQ&A

  • データベースの設計をしています。

    データベースの設計をしています。 ユーザマスタというテーブルがあり、 その中には、個人または企業のデータが入ります。 マスタ登録時に個人と企業は微妙に必須項目が違います。 (例えば、企業の場合は代表者名が入る、など) 要件としては、「企業だけを検索したい」というものもあります。 ここで質問なのですが、 (1)ユーザマスタに「企業フラグ」をつけて、それが「1」のものと検索する (2)代表者名に値が入っているものを検索する この場合、(1)と(2)ではどちらが検索が速いのでしょうか。 (1)の方が、気分的に(なんとなく、です)速い気がするのですが、 (1)だと、余分にカラムを持つことになり、もし(1)も(2)も同じ速さOR(2)の方が速い場合には 無駄だなあ、と思って困っております。 どなたかお詳しい方がいらっしゃいましたら、 どうぞよろしくお願い致します。

    • ベストアンサー
    • MySQL
  • データベースのマスタ設計についての質問

    現在データベースの設計を勉強しています。 マスタの設計について疑問があって質問しました。 【1】すべてのマスタデータを統合したテーブルを作成 カラム1:カテゴリID(PK) カラム2:カテゴリCD(PK) カラム3:値 【2】それぞれのカテゴリに応じたテーブルを作成 カラム1:カテゴリCD(PK) カラム2:値 ※私はパターン1の方が、カテゴリの追加等柔軟かなと考えています。 それぞれのパターンの長所・短所を教えてください。

  • データベースの設計について教えてください。

    データベースの設計について教えてください。 基本的な質問ですみません。宜しくお願いいたします。 単純なテーブルで表現しますが、 パターンA、Bのどちらのテーブルで設計するのが良いのでしょうか。 DBはmysqlで5000万件のデータで検索のみのデータベースです。 【前提】 ユーザは複数のメールアドレスを持ちます。 画面から、このユーザのもつメールアドレスを表示させる仕様だとします。 【userマスタ】 (PK)ユーザID   ユーザ名   会社名 <パターンA> 【mailテーブル】 (PK)ユーザID (PK)ユーザメールアドレス   モバイル用アドレス <パターンB>  【mailテーブル】 (PK)ユーザメールアドレス   モバイル用アドレス   ユーザID ←インデックスをはります。

    • ベストアンサー
    • MySQL
  • 2パターンのデータベース設計で最適なほうはどちら?

    こんにちは。 データベース設計をするにあたり、迷っています。 言語はRuby on rails、DBはMysqlです。 たとえば日記サイトを作るとして (1)テーブル : users , diariesがあって、それぞれのidはuser_diaries というリレーション用のテーブルを作って持たせる (2)テーブル : users , diariesがあって、diaries にuser_id というカラムを持たせる というような作り方ができると思うのですが、どちらが優れていると言えるでしょうか? 決めの問題でしょうか? 将来的に大きなサイトになっても大丈夫なようにしておきたいです

  • データベースのテーブル設計について

    データベースのテーブル設計で、数項目のみのデータをひとつのテーブルにしていますでしょうか? すべてデータベース内で管理するという一貫性はあると思うのですが、たかだか数項目なのでどうかなとも思ってしまいます。 かといって、数項目のみのデータをプログラム内(たとえば構造体)で管理するというのも、管理が必要な要素が散らばるし、再コンパイルも必要になってきます。 このあたりどのようにすればよいのかなといつも判断に悩んでいます。 みなさんはどのように判断、設計していますでしょうか?ご意見お教えください。

  • MySQLで同じデータにフラグ付け出来ますか?

    データベースの初心者です。MySQLを使用してSQL文を試しましたが、うまくいきません。 わかりやすく教えていただけますか? 下のような2つのテーブルで、テーブル2の項目カラムに存在するデータが、 テーブル1の区分にあれば、一致する行(NOカラムの5~7)だけに、 フラグ”1”を付けたいのです。(区分カラムに、"*"で始まるデータは除きます) 区分に、データが全て埋まっていれば簡単に出来るのですが、 先頭行のみデータがあって、次の区分まで、Nullが入っています。 テーブル1 NO 区分 フラグ 1  aaaaa   null 2  null     null 3  null     null 4  null     null 5  bbbbb   null 6  null     null 7  *nozoku  null 8  ccccc null 9  null null テーブル2 NO 項目 1  bbbbb 2  eeeee よろしくお願いします。

    • ベストアンサー
    • MySQL
  • データベーステーブル設計

    簡単なアプリケーションを作ろうとしています。内容は、レストランのデータベースです。画面には、単純にレストラン名、住所、電話番号、営業時間、評価を表示させたいです。この「評価」は、このアプリケーションを使用する3人のユーザが入力する1~5の値の平均値としたいです(ユーザはメンテナンス画面から1レストランにつき1回まで評価値入力可能)。つまりユーザAが4、ユーザBが5、ユーザCが1を入力した場合、4+5+1/3=3.3を表示します。テーブルを設計した経験がないので教えてほしいのですが、この場合、どのようなテーブルを作れば最もシンプルできれいに出来るのでしょうか。まずレストランテーブルを作成する必要があると思いますが、「評価」があるために1テーブルでは不足だと思います。評価カラムの値はユーザが値を入力すれば変動することになるので、別テーブルを参照させるようにすべきなのでしょうか?評価テーブルというものを考えてみましたが、ユーザ名とレストランIDの複合をプライマリキーとし、評価値カラムをもたせるとしても、どこに平均値を持たせればいいのかわかりません。テーブル設計の模範例を教えて頂けると助かります。宜しくお願いします。

  • データベースで変更の多いテーブルの設計

    データベースを設計しています。 あるテーブルに関して、項目(列)が50個くらいあるのですが、これらのうち20個くらいの列が頻繁に変更があり、データの履歴が必要になるため、テーブルを再設計しようと考えています。 現在は変更があるたびにテーブル全体を別テーブルにコピーして、寄せています。 このような場合、何かよい設計方法はあるでしょうか?

  • データベースの設計で質問です。

    会社テーブルがあり、会社がサービス可能な都道府県情報を保存したい場合には、 どのように作るのがいいのでしょうか? 会社テーブルに都道府県別に47個のカラムを追加する 会社テーブル id | name | pref_1 | pref_2 | pref_3 | .... | pref_47 --------------------------------------- 1 | 会社A | 1 | 0 | 1 | .... | 0 2 | 会社B | 0 | 0 | 1 | .... | 1 という感じかなと思ったのですが、カラム数が多くなってしまい、なんとなく冗長な感じがしてしまいます。

  • 映画のデータベースの設計について・・・

    データベースの設計について質問です。 現在、映画のデータベースのようなものを作成しようとしているのですが、そこで、出演者のデータをどのようにしようか悩んでおります。 タイトルごとにユニークなIDをふって、 出演者用のテーブルを作り、タイトルIDと出演者名を結びつけるという方法でいいのでしょうか? この場合・・・ ・タイトルのIDを覚えておく ・出演者用のテーブルに移動し、IDと出演者名を入力する という作業が、出演者の人数分必要になりかなり大変そうなのですが、このような作業を簡略化する方法はあるのでしょうか? わかりにくい文章でもうしわけありません。 どうかよろしくお願いします。