Почему MySQL не использует индекс, когда я включаю подзапрос? - PullRequest
3 голосов
/ 03 марта 2011

У меня есть следующий запрос, который хорош, но будет расти с ростом таблицы брендов:

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 звонка, но это кажется плохим.Я заметил, что могу сделать его немного более эффективным, включив в подзапрос отчет, но это совсем не изменило способ использования ключей.

1 Ответ

4 голосов
/ 03 марта 2011

Почему бы тебе не написать:

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...