mysqlでINは内部的に処理できない 
お久しぶりです。
以前、ボトルネックになっているSQLを探していたら以下のような事がありました。
EXPLAIN SELECT * FROM user_master WHERE user_id IN ( SELECT user_id FROM game_user_status);
とすると
+----+--------------------+------------------+-----------------+---------------+---------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+------------------+-----------------+---------------+---------+---------+------+------+-------------+ | 1 | PRIMARY | user_master | ALL | NULL | NULL | NULL | NULL | 86 | Using where | | 2 | DEPENDENT SUBQUERY | game_user_status | unique_subquery | PRIMARY | PRIMARY | 4 | func | 1 | Using index | +----+--------------------+------------------+-----------------+---------------+---------+---------+------+------+-------------+
86*1
で普通に意図した結果が取得できます。
しかし、サブクエリ中でGROUP BYすると酷いことになりました。
EXPLAIN SELECT * FROM user_master WHERE user_id IN ( SELECT user_id FROM game_user_status GROUP BY user_id);
+----+--------------------+------------------+-------+---------------+---------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+------------------+-------+---------------+---------+---------+------+------+-------------+ | 1 | PRIMARY | user_master | ALL | NULL | NULL | NULL | NULL | 86 | Using where | | 2 | DEPENDENT SUBQUERY | game_user_status | index | NULL | PRIMARY | 4 | NULL | 67 | Using index | +----+--------------------+------------------+-------+---------------+---------+---------+------+------+-------------+
GROUP BYすると
86*67
と、検索ロジックに大きな違いが出てきます。
で、原因は”IN”句
MySQLは内部的にINを直接処理することができないので、EXISTSに変換することでSQL的には相関のないサブクエリも相関サブクエリになってしまうのである。これがまさにMySQLのサブクエリが遅い!と言われている原因だろう。
なぜMySQLのサブクエリは遅いのか。
だからってGROUP BY使っただけでそこまでしなくても・・・
と、いう事で以下のように書き換えると解決できるようです。
EXPLAIN SELECT * FROM user_master um WHERE EXISTS (SELECT 1 FROM game_user_status gus WHERE um.user_id = gus.user_id);
+----+--------------------+-------+--------+---------------+---------+---------+-----------------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+-------+--------+---------------+---------+---------+-----------------------+------+-------------+ | 1 | PRIMARY | um | ALL | NULL | NULL | NULL | NULL | 86 | Using where | | 2 | DEPENDENT SUBQUERY | gus | eq_ref | PRIMARY | PRIMARY | 4 | warui_test.um.user_id | 1 | Using index | +----+--------------------+-------+--------+---------------+---------+---------+-----------------------+------+-------------+
個人のブログの方でご指摘いただきました内容を解答例とさせていただいています。
安直にINを利用するのは良くないという例でした。
ちなみにgroup by してもしなくても取得結果が変わらない場合もあります。
今回の例なんかはgroup by しなくても取得結果は変わりません。
むやみやたらと色々つければいいって物でも無い いい例です。