質問するログイン新規登録

回答編集履歴

2

追加情報を加味した回答を追記

2016/04/14 08:35

投稿

KiyoshiMotoki
KiyoshiMotoki

スコア4791

answer CHANGED
@@ -63,4 +63,33 @@
63
63
  どうしても改善できない場合、苦肉の策として、Javascriptなどを使って問題のデータを非同期で取得する、とかでしょうか。。
64
64
 
65
65
  ちなみに、ご提示のクエリだとペットを飼っている人が1人もいない趣味は結果に含まれないことになりますが、
66
- それは問題ないでしょうか?
66
+ それは問題ないでしょうか?
67
+
68
+ ---
69
+
70
+ `FORCE INDEX`が聞いたということでしたら、以下2通りのクエリを試していただけますでしょうか?
71
+ ```sql
72
+ SELECT t_syumi.syumi_id, t_syumi.syumi_name, tmp.cnt
73
+ FROM t_syumi
74
+ INNER JOIN (
75
+ SELECT syumi_id, COUNT(DISTINCT pet_name) AS cnt
76
+ FROM t_petlist
77
+ FORCE INDEX FOR GROUP BY (pet_name)
78
+ INNER JOIN t_setting ON t_setting.user_id = t_petlist.user_id
79
+ GROUP BY syumi_id
80
+ ) AS tmp ON t_syumi.syumi_id = tmp.syumi_id
81
+ ORDER BY cnt DESC;
82
+ ```
83
+
84
+ ```sql
85
+ SELECT t_syumi.syumi_id, t_syumi.syumi_name, tmp.cnt
86
+ FROM t_syumi
87
+ INNER JOIN (
88
+ SELECT syumi_id, COUNT(DISTINCT pet_name) AS cnt
89
+ FROM t_setting
90
+ FORCE INDEX FOR GROUP BY (syumi_id)
91
+ INNER JOIN t_petlist ON t_setting.user_id = t_petlist.user_id
92
+ GROUP BY syumi_id
93
+ ) AS tmp ON t_syumi.syumi_id = tmp.syumi_id
94
+ ORDER BY cnt DESC;
95
+ ```

1

回答を追記

2016/04/14 08:35

投稿

KiyoshiMotoki
KiyoshiMotoki

スコア4791

answer CHANGED
@@ -1,4 +1,66 @@
1
1
  問題が`DISTINCT`句であることが特定できているようですので、以下のページが参考になるかもしれません。
2
2
  [https://dev.mysql.com/doc/refman/5.6/ja/distinct-optimization.html](https://dev.mysql.com/doc/refman/5.6/ja/distinct-optimization.html)
3
3
 
4
- また、"情報の追加・修正の依頼をする"欄に記載させていただいた情報を追記いただけると、より詳しい状況がわかるので、具体的な回答を得やすくなると思います。
4
+ また、"情報の追加・修正の依頼をする"欄に記載させていただいた情報を追記いただけると、より詳しい状況がわかるので、具体的な回答を得やすくなると思います。
5
+
6
+ ---
7
+
8
+ 情報の追記、ありがとうございます。
9
+
10
+ 一見したところ、インデックスのつけ方は問題ないように見受けます。
11
+
12
+ こちらで15万件ものデータを投入した環境を用意することができないので、
13
+ 以下に、同様の結果を得られ(ると思う)、かつパフォーマンスの改善が見込めそうなクエリを
14
+ いくつか挙げさせていただきます。
15
+
16
+ #### ケース1 : JOINする順番を変更(レコードの少ないテーブルからJOIN)
17
+ ```sql
18
+ SELECT t_syumi.syumi_id, syumi_name, COUNT(DISTINCT pet_id) AS cnt
19
+ FROM t_syumi INNER JOIN t_setting ON t_syumi.syumi_id = t_setting.syumi_id
20
+ INNER JOIN t_petlist ON t_setting.user_id = t_petlist.user_id
21
+ GROUP BY t_syumi.syumi_id
22
+ ORDER BY cnt DESC
23
+ ;
24
+ ```
25
+
26
+ #### ケース2 : ケース1に加えて、`DISTINCT`句を排除
27
+ ```sql
28
+ SELECT t_syumi.syumi_id, syumi_name, COUNT(pet_id) AS cnt
29
+ FROM t_syumi
30
+ INNER JOIN t_setting ON t_syumi.syumi_id = t_setting.syumi_id
31
+ INNER JOIN t_petlist ON t_setting.user_id = t_petlist.user_id
32
+ GROUP BY t_syumi.syumi_id
33
+ ORDER BY cnt DESC
34
+ ;
35
+ ```
36
+
37
+ #### ケース3 : ケース2に加えて、レコード数を絞り込んでからJOIN(hirohiro様の回答と同様)
38
+ ```sql
39
+ SELECT t_syumi.syumi_id, syumi_name, cnt
40
+ FROM t_syumi INNER JOIN (
41
+ SELECT syumi_id, COUNT(*) AS cnt FROM t_setting
42
+ INNER JOIN t_petlist ON t_setting.user_id = t_petlist.user_id
43
+ GROUP BY syumi_id
44
+ ) AS tmp ON t_syumi.syumi_id = tmp.syumi_id
45
+ ORDER BY cnt DESC
46
+ ;
47
+ ```
48
+
49
+ #### ケース4 : ケース3に加えて、`FORCE INDEX`句を使用
50
+ [https://dev.mysql.com/doc/refman/5.6/ja/index-hints.html](https://dev.mysql.com/doc/refman/5.6/ja/index-hints.html)
51
+ ```sql
52
+ SELECT t_syumi.syumi_id, syumi_name, cnt
53
+ FROM t_syumi INNER JOIN (
54
+ SELECT syumi_id, COUNT(*) AS cnt FROM t_setting
55
+ FORCE INDEX FOR GROUP BY (syumi_id)
56
+ INNER JOIN t_petlist ON t_setting.user_id = t_petlist.user_id
57
+ GROUP BY syumi_id
58
+ ) AS tmp ON t_syumi.syumi_id = tmp.syumi_id
59
+ ORDER BY cnt DESC
60
+ ;
61
+ ```
62
+
63
+ どうしても改善できない場合、苦肉の策として、Javascriptなどを使って問題のデータを非同期で取得する、とかでしょうか。。
64
+
65
+ ちなみに、ご提示のクエリだとペットを飼っている人が1人もいない趣味は結果に含まれないことになりますが、
66
+ それは問題ないでしょうか?