効率的なDBの構造とは?

このQ&Aのポイント
  • 大量のカラムが検索対象の場合、効率的なDBの構造を考える必要があります。
  • phpからmysqlのクエリを使ってコンテンツを検索・絞り込む方法を考えています。
  • テーブルを分けることで管理しやすくなり、絞り込みやソートの機能を実現しています。
回答を見る
  • ベストアンサー

大量のカラムが検索対象の場合の効率的なDBの構造

phpからmysqlのクエリを作りコンテンツを検索・絞り込みさせようと考えています。 説明するのが苦手なため画像での説明になってしまいますが、 データベースの構造 http://blog-imgs-54.fc2.com/s/k/s/sksfiosjdijf34/20120614-1.jpg 絞り込みページのイメージ http://blog-imgs-54.fc2.com/s/k/s/sksfiosjdijf34/20120614-2.jpg 種類テーブルだけは「名前」が決まれば「仲間」と「原産地」が決まるので正規化することができましたが、他はできないと思います。 現在所在地テーブルはできそうですが、市によって町名が重なってしまうところがあるので正規化していません。 特徴テーブルは、種類による一般的な特徴よりも実際の特徴を優先しているので、同じ種類でも特徴がそれぞれ違います。 テーブルを分けている理由は、その方が管理しやすいと思ったからです。 特徴テーブル、日付テーブルも同じ理由です。 コメントテーブルのデータは検索しません。 「番号」には主キーを、種類テーブルは「名前」のみ、その他のカラムには全てインデックスをつけます。コメントテーブルはつけません。 そして、絞り込みページでは、 それぞれのカラムでソートさせる機能もあります。 「絞り込み」を押すと選択した条件に全て一致するコンテンツを絞り込みます。 「詳細へ」を押すと詳細のページに入り、 詳細のページでは、そのフィールドの全てのカラムのデータを表示させます。 もっと早く検索でき、効率的な構造にしたいのですが、アドバイスをいただけないでしょうか。

  • MySQL
  • 回答数3
  • ありがとう数3

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

  • ベストアンサー
回答No.2

(1)文字列にインデックスをつけてもINSERT時のコストの割りに高速化しないので文字列にはインデックスをつけない。 (2)文字列を結合に使わない。 (3)出来るだけINTなどの数値で検索する DBの定義はこのようにしてみました。 -- -- テーブルの構造 `MST_COLOR` -- CREATE TABLE IF NOT EXISTS `MST_COLOR` ( `ID_COLOR` int(11) NOT NULL AUTO_INCREMENT, `COLOR_NAME` varchar(2) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (`ID_COLOR`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='毛色マスター' AUTO_INCREMENT=1 ; -- -- テーブルの構造 `MST_SPECIES` -- CREATE TABLE IF NOT EXISTS `MST_SPECIES` ( `ID_SPECIES` int(11) NOT NULL AUTO_INCREMENT COMMENT '犬種ID', `SPECIES_NAME` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '犬種名', `COUNTRY` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '原産国', `COMPANY` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '仲間', PRIMARY KEY (`ID_SPECIES`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='種類マスタ' AUTO_INCREMENT=1 ; -- -- テーブルの構造 `TBL_KOBETSU` -- CREATE TABLE IF NOT EXISTS `TBL_KOBETSU` ( `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '番号', `ID_SPECIES` int(11) NOT NULL COMMENT '犬種ID', `PRICE` float NOT NULL COMMENT '価格', `SEX` tinyint(1) NOT NULL COMMENT '性別', `HEIGHT` float NOT NULL COMMENT '体高', `WEIGHT` float NOT NULL COMMENT '体重', `ID_COLOR` int(11) NOT NULL COMMENT '毛色', `AVG_AGE` int(2) NOT NULL COMMENT '平均寿命', `DISEASE` set('無し','有り') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '病気有無', `PEDIGREE` set('無し','有り') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '血統書有無', `PREF` varchar(16) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '都道府県', `CITY` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '市区', `TOWN` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '町', `BIRTHDAY` date NOT NULL COMMENT '誕生日', `UPDATE_DATE` date NOT NULL COMMENT '掲載日', `COMMENT` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `POINT_CARE` set('1','2','3','4','5') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `POINT_NEIGHBORLY` set('1','2','3','4','5') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `POINT_SECURITY` set('1','2','3','4','5') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `POINT_DEFENSE` set('1','2','3','4','5') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `POINT_COLD` set('1','2','3','4','5') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `POINT_HEAT` set('1','2','3','4','5') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `POINT_PLAY` set('1','2','3','4','5') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `POINT_LIVELY` set('1','2','3','4','5') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `POINT_EXERCISE` set('1','2','3','4','5') CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (`ID`), KEY `ID_SPECIES` (`ID_SPECIES`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='個別テーブル' AUTO_INCREMENT=1 ;

kiseki777
質問者

お礼

ありがとうございます。凄く参考になりました。 書いて頂いたクエリを図にしました。 http://blog-imgs-54.fc2.com/s/k/s/sksfiosjdijf34/2012-06-16_003547.jpg 検索とソートする場合は下記のようになりますか? 【絞り込み】 SELECT * FROM dog_database WHERE ID_SPECIES=8 AND BETWEEN 価格 50.0 and 60.0 AND 性別='メス' AND BETWEEN 体高 15.0 and 20.0 AND BETWEEN 体重 4.0 and 5.0 AND ID_COLOR=3 AND 平均寿命=11 AND 病気='無し' AND 血統書='有り' AND 県='神奈川県' AND 市='横浜市' AND 町='一' AND BETWEEN 誕生日 2012/1 and 2012/6 AND BETWEEN 掲載日 1990/1 and 2012/6 AND 手入れ=5 AND 人懐こさ=1 AND 番犬適性=2 AND 防衛能力=3 AND 耐寒能力=5 AND 耐暑能力=1 AND 遊び好き度=2 AND 活発度=4 AND 必要運動量=2 ORDER BY 番号 LIMIT 0,30; 【ソート】 ○○○のソートを押された時、指定された検索条件のままでソートしたいので、 上記クエリをそのまま使い、最後のORDER BYのカラム指定だけを○○○に変える。 SELECT * FROM dog_database WHERE ID_SPECIES=8 AND ---上記クエリと同じ--- ORDER BY ○○○ LIMIT 0,30; ID_SPECIESだけにインデックスをつけることと、 InnoDB型でなくMyISAM型を選ぶのはなぜでしょうか?

その他の回答 (2)

回答No.3

補足について MyISAMでもInnoDBでもどちらでもよろしいと思います。このようなシンプルな構造のデータベースだからトランザクションがどうしても必要というわけではないだろうということと、MySQLのバージョンの指定がなかったので、MyISAMにしておいたほうが、問題がないだろうということです。 > ID_SPECIESだけにインデックスをつける インデックスは付けすぎるとパフォーマンスが低下します。 ID_SPECIESはテーブルを結合するフィールドだからです。 それ以外のフィールドへのインデックスは、実際にデータが入ってから、遅いクエリが発生する場合にチューニングすることで使用するかもしれない選択肢としてとっておきます。 はじめから決め打ちはしません。

kiseki777
質問者

お礼

ありがとうございます。 >MyISAMでもInnoDBでもどちらでもよろしいと思います。 >このようなシンプルな構造のデータベースだからトランザクションがどうしても >必要というわけではないだろうということと、MySQLのバージョンの指定がなかったので、 >MyISAMにしておいたほうが、問題がないだろうということです。 MyISAMがおすすめなんですね。それを基本にします。 >インデックスは付けすぎるとパフォーマンスが低下します。 >ID_SPECIESはテーブルを結合するフィールドだからです。 >それ以外のフィールドへのインデックスは、実際にデータが入ってから、 >遅いクエリが発生する場合にチューニングすることで >使用するかもしれない選択肢としてとっておきます。 >はじめから決め打ちはしません。 インデックスは更新時に負荷が大きい、なので必要な分だけを適切に付けていくんですね。 付けるときの優先順位は別のテーブルから結合するフィールドからですね。 この状態でもパフォーマンスが遅い時には、 毛の色テーブルが結合するフィールドなので、 今度は毛の色にインデックスを付ければいいということですか。 前回のお例文に画像のURLをはり、きちんと確認したのですが、 なぜかサーバーから画像が消えてしまいました。すみませんでした。 もしよろしければ確認してください。 http://blog-imgs-54.fc2.com/s/k/s/sksfiosjdijf34/201206161934148ba.jpg

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.1

個別テーブル、現在所在地テーブル、特徴テーブル、日付テーブルは とくに二重に持ったり頻繁な可変で履歴性が必要なデータでもないし 番号にIDされる個々の犬に紐づくので分ける必要がないのでは? 見づらいというならビューをつかえばよいでしょう

kiseki777
質問者

お礼

>番号にIDされる個々の犬に紐づくので分ける必要がないのでは? すみません。一番大事な理由を書き忘れていました。 16個までしかインデックスをつけられない、という問題があります。 テーブルを無理やり分けた一番の理由は、これを回避するためです。 >見づらいというならビューをつかえばよいでしょう ありがとうございます。試してみます。

関連するQ&A

  • 【花】フヨウの種類、わかる人いますか?

    かわいい花の咲くフヨウという木があります。 道端で見かけたフヨウが気に入ったのですが、種類の名前が分からず調べることができません。 画像検索をしたところ、こちらの画像に葉と花の形がよく似ています。 http://blog-imgs-55.fc2.com/m/i/n/minamitsukaguchi/209011.jpg http://blog-imgs-55.fc2.com/m/i/n/minamitsukaguchi/209012.jpg http://blog-imgs-55.fc2.com/m/i/n/minamitsukaguchi/209013.jpg このフヨウの正式な名称がわかる方いらっしゃいますか? お心当たりのある方、ご回答お待ちしております。

  • この木の名前が分かりません。

    こんにちは。 この木の名前が分からず困っています。 幹の感じ http://blog-imgs-54.fc2.com/n/e/w/newskywindow/kidesu.jpg 枝の伸び方 http://blog-imgs-54.fc2.com/n/e/w/newskywindow/022.jpg 葉っぱの特徴 http://blog-imgs-54.fc2.com/n/e/w/newskywindow/023.jpg この前見たとき(5月下旬)、6mmくらいの小さな緑の実がなっていました。 よろしくお願いします。

  • 1000件以下の場合はカラム数に関係なくキー不要?

    全てのカラムを対象にソートや絞り込みをする、また、テーブルを分割する必要がない場合、 全てのカラムにインデックスをつけるしかないと考えていましたが、 http://www28.atwiki.jp/lucier/pages/55.html 「MySQLでは1000件以下のデータの場合はインデックスを作成しないほうが 速い」 1000フィールドならカラムの数に関係なくインデックス不要で カラムの数が10の場合と、 カラムの数が50の場合 それぞれ負荷はかわらないということでしょうか。

    • ベストアンサー
    • MySQL
  • どの研ぎ石がいいの?

    包丁の切れ味が悪いので、研ぎ石を100均で買いたいのですが、 http://hakataseabasslure.blog.fc2.com/img/KIMG9027.jpg/ http://blog-imgs-12.fc2.com/b/o/k/bokkyun/002_20101206193953.jpg http://blog-imgs-47-origin.fc2.com/h/a/m/hamonotogiya/kanitogiki01.jpg こういった3種類が販売されてることが多く迷ってます。 どれがいいのでしょうか? 違いってあるんですか?

  • どこに行けば、こんな可愛い子と知り合えるの?

    http://blog-imgs-23.fc2.com/a/r/k/arknashippo/20070129222340.jpg http://blog-imgs-23.fc2.com/a/r/k/arknashippo/20070129222353.jpg http://blog-imgs-27.fc2.com/k/a/g/kagekumakatsu/20080816171829.jpg http://pds.exblog.jp/pds/1/200904/09/36/e0078836_2051282.jpg

  • この絵師を教えてください

    http://blog-imgs-24.fc2.com/p/i/c/picture2ch2/viploader966508.jpg http://blog-imgs-24.fc2.com/p/i/c/picture2ch2/sukima012917.jpg http://blog-imgs-24.fc2.com/p/i/c/picture2ch2/viploader966515.png http://blog-imgs-24.fc2.com/p/i/c/picture2ch2/viploader966513.jpg http://blog-imgs-24.fc2.com/p/i/c/picture2ch2/sukima012975.jpg それぞれの画像の絵師を教えていただけませんか? 分かるのだけで結構です。

  • コラムの値からコラム・テーブルを検索

    プライマリキーが様々なテーブルで別の名前で利用されていると、テーブル同士の関連の全てが把握できずに困っています。以前にコラム名からテーブルを検索する方法を質問したのですが、私が扱っているデータベースでは、プライマリキーがシステムの別の場所で少しだけ異なる名前で利用されていることが多いので、その方法では把握できない関連が出てきます。 具体的には、EMPLOYEES__KEYというEMPLOYEESテーブルのプライマリキーがPERSONALIZE_EMPOYEESというテーブルでPSNLZ_EMP__KEYという名前で使われている状況を考えていただきたいと思います。PSNLZ_EMP__KEYのコラムのレコードは全てEMPLOYEES__KEY内のデータからとられているとします。 以前にselect TABLE_NAME from USER_TAB_COLUMNS where COLUMN_NAME = 'EMPLOYEES__KEY' というSQLで特定のコラムを使っているテーブルを全てリストアップできると教えていただいたのですが、今回のケースでは、同じような内容のコラムなのですが名前が異なるため上記のSQLでは検索できないテーブルがある場合、それをどうやってとってきたらよいのかということです。 コラムの値にtaro, jiro, hanakoなどのようにテーブルまたはシステム内でユニークな値が指定されている場合、コラムの値を指定し、「その値が使われているコラム・テーブルを列挙せよ」というような命令を与えればよいのだということまでは分かりますが、どのようにSQLを書けば良いか教えてください。

  • 【画像あり】空が赤い

    空が赤くなる理由は何ですか? 画像 http://livedoor.blogimg.jp/ringotomomin/imgs/6/7/672e8846-s.jpg http://blog-imgs-37-origin.fc2.com/n/e/e/neetetsu/20110317032231_1_1.jpg 引用元: http://blog.livedoor.jp/ringotomomin/archives/51536804.html http://neetetsu.blog109.fc2.com/blog-entry-995.html

  • 画像のキャラクター名と作品名を

    http://blog-imgs-56.fc2.com/a/s/d/asdfqwer683/201206001000033.jpg ご存知の方、どなたか教えて頂けませんでしょうか?

  • この人誰ですか?

    この人誰ですか? http://blog-imgs-51.fc2.com/s/a/n/sanzierogazo/nz19203221023.jpg