2011-03-03 113 views
3

我有以下查询,这是很好的,但将获得更慢的品牌表的增长:为什么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 
    ->      (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) 

为什么不使用主键索引这里做了,我不明白文件排序。如果我用从子查询返回的值替换子查询,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) 

这是为什么?这对我来说并不合适。我的意思是,我可以把它分成2个电话,但这似乎很差。我确实注意到,通过在子查询中包含独特的内容,我可以使其效率稍高一些,但这并没有改变它使用密钥的方式。

回答

4

你为什么不写探微:

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; 
+0

是啊,这工作。过于专注于试图弄清楚为什么它不使用索引来考虑将其重构为不那么愚蠢。 :) – ctide 2011-03-03 19:13:13

相关问题