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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

4回答

1581閲覧

MySQLのindexの張り方について

supermaruetsu

総合スコア148

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

0クリップ

投稿2017/10/27 02:58

編集2017/10/27 10:22

下記のようなテーブルに5万件程度のデータが入っております。
データの中身ですが、映画のタイトル(日本語と英語)、登場人物が入力されております。
title_jp,title_en,characterそれぞれでユーザーが部分検索をする仕様です。

この場合、どのようにIndexを張ればよいでしょうか。
title_jp,title_en,characterの3つを複合Indexとするのがいいのではないかと考えておりますが、
いかがでしょうか。

id,title_jp,title_en,character,
3094,エアマスター,Air Master,Tachibana,
3095,エアマスター,Air Master,Tomiko Seriguchi,
3096,エアマスター,Air Master,Tsukio Taketsugu,
3097,エアマスター,Air Master,Yoshinori Konishi,
3098,エアマスター,Air Master,Yuukorin,

補足)
用途や構成など分かりにくい部分が多く申し訳ありませんでした。
まず構成ですが、参考のURLのように一つのフォームで映画のタイトルや出演者を同時に検索+サジェスト機能を持ったものをイメージしていただければと思います。

ツタヤタイトル検索

この検索に引っかかるように、ユーザーが部分検索をしている際にAjaxでDBにアクセス、サジェスト結果を下に出るウインドウに表示させます。
ユーザーが該当の選択肢(該当タグ)を選び、「検索」ボタンを押すと、バインドされているtag_idを投げ、別に用意されているuser_idとtag_idが入力された中間テーブルをもとに同じタグをお気に入り登録しているユーザーの情報を「検索結果」として表示できます。

この「サジェスト」は例に挙げているtitle_jp,title_en,characterの全ての結果が必要となります。
その為、それぞれのデータを正規化し各自で保有しておくと、検索の際3つのテーブルをスキャン、該当のデータを見つけた後に3つのjoinが必要となるので逆に辛くなるのではと考えております。
知識がないので誤った考えかもしれません。

アドバイスを頂ければ幸いです。よろしくお願い致します。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2017/10/27 02:59

「部分検索」とありますが、「各列ごとに部分一致で検索する」ということで間違いないでしょうか。
supermaruetsu

2017/10/27 03:04

はい、その通りでございます。よろしくお願い致します。
guest

回答4

0

ベストアンサー

MySQLで、column LIKE %ほげ%と部分一致検索をするとき、有効なインデックスはありません。ということで、インデックスが必要なら手段は次のいずれかです。

  • MySQL上でフルテキストインデックスを構築して、MATCH AGAINSTで検索する
  • 全文検索エンジンを別に入れる

投稿2017/10/27 04:11

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

見た感じindexの貼り方云々の前段階です
正規化のために映画テーブルをつくって

eiga_id,title_jp,title,en
1,エアマスター,Air Master

を外出しにして下さい

また本来俳優も俳優テーブルで
haiyu_id,character
1,Tomiko Seriguchi
2,Tsukio Taketsugu
3,Yoshinori Konishi
4,Yuukorin

とします。その上で
id,eiga_id,haiyu_id
3094,1,1
3095,1,2
3096,1,3
3097,1,4
3098,1,5

をとっておくのが妥当です。
この場合のインデックスはeiga_id,haiyu_idの複合インデックスが良いでしょう

sample

  • テーブル作成

SQL

1create table eiga(eiga_id int primary key,title_jp varchar(30),title_en varchar(30)); 2insert into eiga values(1,'エアマスター','Air Master'); 3 4create table haiyu(haiyu_id int primary key,`character` varchar(30)); 5insert into haiyu values 6(1,'Tomiko Seriguchi'), 7(2,'Tsukio Taketsugu'), 8(3,'Yoshinori Konishi'), 9(4,'Yuukorin'); 10 11create table shukei(id int primary key,eiga_id int,haiyu_id int,unique(eiga_id,haiyu_id)); 12insert into shukei values 13(3094,1,1), 14(3095,1,2), 15(3096,1,3), 16(3097,1,4), 17(3098,1,5);
  • 全データ表示

SQL

1select t1.id,t2.title_jp,t2.title_en,t3.character 2from shukei as t1 3inner join eiga as t2 on t1.eiga_id=t2.eiga_id 4inner join haiyu as t3 on t1.haiyu_id=t3.haiyu_id 5
  • 特定の俳優を抽出

SQL

1select t1.id,t2.title_jp,t2.title_en,t3.character 2from shukei as t1 3inner join eiga as t2 on t1.eiga_id=t2.eiga_id 4inner join haiyu as t3 on t1.haiyu_id=t3.haiyu_id 5and t3.character='Yoshinori Konishi'

投稿2017/10/27 03:05

編集2017/10/27 11:48
yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

supermaruetsu

2017/10/27 03:49 編集

私の理解不足によるコメントになってしまうかもしれませんが失礼します。これはタグサーチで「意図するタグを探し、自分のお気に入りとして別のテーブルに追加する」為のテーブルになります。別のテーブルとは、そのユーザーのお気に入りを管理する、user_idとtag_idで構成される中間テーブルになります。 言わんとしていることは、ひとつのフォームでタイトルor登場人物を部分検索し、該当のtag_idを見つけるには、テーブルを切り分けるのは手間になるのではないか?という事です。
yambejp

2017/10/27 03:51

> ひとつのフォームでタイトルor登場人物を部分検索し、該当のtag_idを見つけるには、テーブルを切り分けるのはNGだということです。 ごめんなさい、状況がよくわかりません。 特殊なDBで管理しているならともかく、MySQLなど標準的なDBでは正規化しないという選択肢は あまり考えられません。 もし正規化しない場合は、文字の微妙なブレ(大文字小文字・全角半角・不要なスペース文字)など ヒューマンエラーにより、ただしい検索や集計ができなくなる可能性が高くなります。 それでもどうしてもというのであれば、ご提示の方式でやるのは構いません。 その場合はインデックスはたぶんなにをやっても最適にはならないので、 適当にトライアンドエラーでやるしかないでしょうね
supermaruetsu

2017/10/27 04:32

ご回答ありがとうございます。 状況がうまく説明できるように、整理して補足を付け加えてみます!もし可能であれば、後ほどご確認頂ければ幸いです。
yambejp

2017/10/27 11:50

補足をみましたが、正規化をしない理由になっていません。 なにを危惧しているのかわかりませんが、普通に正規化してインデックスを張ればいいと思います (サンプル付けておきました)
supermaruetsu

2017/10/30 10:14

再度のご回答ありがとうございました。BAは高評価の多い方にさせて頂きましたが、個人的に最も参考になる回答を頂けたと感じております。今後ともよろしくお願いいたします。
guest

0

まずは正規化した方が良いと思います。
同じテーブルに同じデータをひたすら持つのは領域も無駄ですし
全て部分一致で探すのは遅くなるんじゃないかと・・・。

title_jp,title_en、characterは別テーブルに切り出して
IDでリレーションしておくのがオーソドックスパターンです。

それならば部分一致検索するデータ量も減り
あとはID完全一致で紐づけられるのでいいと思います。

投稿2017/10/27 04:18

yuki-saito

総合スコア928

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

インデックスによる高速化ということなら全文検索しかなさそうですけど、日本語が含まれるので、分かちまでを考慮するなら、他の全文検索エンジンってことになりそうですね。

別なアプローチとしては、インデックスにはなから期待せずにデータ件数を少なくすることを考えてはどうですか。

id,title_jp,title_en,character
3094,エアマスター,Air Master,'Tachibana','Tomiko Seriguchi','Tsukio Taketsugu',・・・

のように、俳優を配列で持つようなイメージです。

件数がどの程度圧縮されるか分かりませんが、少なくともタイトル部分に関しては、圧縮率が高ければそれなりに効果は期待できると思います。

投稿2017/10/27 07:39

編集2017/10/30 11:38
sazi

総合スコア25195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問