[英]Why is MySQL not using an index when I'm including a subquery?
I have the following query, which is fine, but will get slower as the brands table grows: 我有以下查询,这很好,但随着品牌表的增长会变慢:
mysql> explain select brand_id as id,brands.name from tags
-> INNER JOIN brands on tags.brand_id = brands.id
-> where brand_id in
-> (select brand_id from tags where outfit_id in
-> (1,6,68,265,271))
-> group by brand_id, brands.name
-> ORDER BY count(brand_id)
-> LIMIT 5;
+----+--------------------+--------+----------------+------------------------------------------------+------------------------+---------+-----------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+--------+----------------+------------------------------------------------+------------------------+---------+-----------------+------+----------------------------------------------+
| 1 | PRIMARY | brands | ALL | PRIMARY | NULL | NULL | NULL | 165 | Using where; Using temporary; Using filesort |
| 1 | PRIMARY | tags | ref | index_tags_on_brand_id | index_tags_on_brand_id | 5 | waywn.brands.id | 1 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | tags | index_subquery | index_tags_on_outfit_id,index_tags_on_brand_id | index_tags_on_brand_id | 5 | func | 1 | Using where |
+----+--------------------+--------+----------------+------------------------------------------------+------------------------+---------+-----------------+------+----------------------------------------------+
3 rows in set (0.00 sec)
I don't understand why it isn't using the primary key as the index here and doing a file sort. 我不明白为什么它不使用主键作为索引并进行文件排序。 If I replace the subquery with the values returned from that subquery, MySQL correctly uses the indices:
如果我用从该子查询返回的值替换子查询,MySQL正确使用索引:
mysql> explain select brand_id as id,brands.name from tags
-> INNER JOIN brands on tags.brand_id = brands.id
-> where brand_id in
-> (2, 2, 9, 10, 40, 32, 9, 118)
-> group by brand_id, brands.name
-> ORDER BY count(brand_id)
-> LIMIT 5;
+----+-------------+--------+-------+------------------------+------------------------+---------+-----------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+------------------------+------------------------+---------+-----------------+------+----------------------------------------------+
| 1 | SIMPLE | brands | range | PRIMARY | PRIMARY | 4 | NULL | 6 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | tags | ref | index_tags_on_brand_id | index_tags_on_brand_id | 5 | waywn.brands.id | 1 | Using where; Using index |
+----+-------------+--------+-------+------------------------+------------------------+---------+-----------------+------+----------------------------------------------+
2 rows in set (0.00 sec)
mysql> explain select brand_id from tags where outfit_id in (1,6,68,265,271);
+----+-------------+-------+-------+-------------------------+-------------------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------------+-------------------------+---------+------+------+-------------+
| 1 | SIMPLE | tags | range | index_tags_on_outfit_id | index_tags_on_outfit_id | 5 | NULL | 8 | Using where |
+----+-------------+-------+-------+-------------------------+-------------------------+---------+------+------+-------------+
1 row in set (0.00 sec)
Why would this be? 为什么会这样? It doesn't really make sense to me.
这对我来说真的没有意义。 I mean, I can break it up into 2 calls, but that seems poor.
我的意思是,我可以把它分成2个电话,但这看起来很糟糕。 I did notice that I can make it slightly more efficient by including a distinct in the subquery, but that didn't change the way it uses keys at all.
我注意到我可以通过在子查询中包含一个独特的内容来使它更有效,但这并没有改变它使用键的方式。
Why don't you juste write : 你为什么不写作:
SELECT brand_id as id,brands.name
FROM tags
INNER JOIN brands ON tags.brand_id = brands.id
WHERE outfit_id in (1,6,68,265,271)
GROUP BY brand_id, brands.name
ORDER BY count(brand_id)
LIMIT 5;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.