2011-03-03 109 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

相關問題