有什么办法可以禁止MySQL在使用索引找不到结果时进行全表扫描?
例如这个查询:
SELECT *
FROM a
WHERE (X BETWEEN a.B AND a.C)
ORDER BY a.B DESC
LIMIT 1;
只有当 X 满足条件并且至少返回 1 行时才有效,但如果表中的任何数据都不满足条件,则会执行全扫描,这可能会非常昂贵。
我不想优化这个特定的查询,它只是一个例子。
对于 X 在范围内或范围外的查询进行解释:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE a range long_ip long_ip 8 \N 116183 100.00 Using where
STATUS VARIABLE 显示更好的信息。对于超出范围的 X:
Handler_read_prev 84181
Key_read_requests 11047
在范围内:
Handler_read_key 1
Key_read_requests 12
要是有办法防止 Handler_read_prev 增长到超过 1 就好了。
更新。我不能接受我自己的回答,因为它并没有真正回答问题(尽管 HANDLER 是一个很棒的功能)。在我看来,没有通用的方法来阻止 MySQL 进行全面扫描。虽然像 key='X' 这样的简单条件将被视为“不可能的地方”,但像 BETWEEN 这样的更复杂的条件不会。
最佳答案
您可以编写一个“完全覆盖”的子查询,它只使用索引中可用的数据。根据返回的主键,您可以在主表中查找行。
以下查询完全由 (id)、(B,id) 和 (C,id) 上的索引覆盖:
select *
from a
where id in (
select id
from a
where x <= C
and id in (
select id
from a
where B <= X
)
)
limit 1
每个 SELECT 使用一个索引:最里面的索引 (B,id);中间的 SELECT 使用 (C,id) 上的索引,而外部的 SELECT 使用主键。
关于sql - 禁止 MySQL 对查询使用全表扫描,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1617317/