假设在这个明显人为的示例中有三个表Parts
、Brand
和Warehouse
。
Parts具有id、brand_id和warehouse_id index_parts_on_brand_id index_parts_on_brand_id_and_warehouse_id
我们跑
SELECT COUNT(*) FROM `parts` WHERE `parts`.`brand_id` = {some_id};
当我对一个拥有大量部件(在本例中为700万)的品牌运行此查询并检查查询计划时,我可以看到mysql使用index_parts_on_brand_id_and_warehouse_id
索引。
如果我强制mysql使用index_parts_on_brand_id
,如下所示:
SELECT COUNT(*) FROM `parts` FORCE INDEX (index_parts_on_brand_id) WHERE `parts`.`brand_id` = {some_id};
使用每个索引时:index_parts_on_brand_id
- 类型:参考
- extra:使用索引
- 必须查看13,012,370行13,012,370
index_parts_on_brand_id_and_warehouse_id
- 类型:参考
- extra:使用索引
- 必须查看2,391,314
我很惊讶地看到,数据库在使用index_parts_on_brand_id
时不得不多看近1100万条记录。
为什么mysql必须查看这么多额外的行?我希望mysql在使用index_parts_on_brand_id
和index_parts_on_brand_id_and_warehouse_id
时必须查看相同或更少的行
谢谢大家!
1条答案
按热度按时间tzdcorbm1#
“必须查看13,012,370行”--这是一个谬论。
EXPLAIN
* 估计 * 它呈现给你的数字。有时它们相差很远。不要相信它们。另一方面,do trust
extra: Using index
。这意味着INDEX
是“覆盖”的,这意味着它使用了索引的BTree而不是数据的BTree。这很好。但是,…它仍然需要查看数百万行。
要获取“触摸”的确切行数,可以使用
EXPLAIN ANALYZE
(如果可用)或使用Handler
值:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#handler_counts我真的需要看到
SHOW CREATE TABLE
和查询的完整示例。这里有一个常见的错误,可以防止使用索引:陷阱是将字符串列与数字文字进行比较。