【发布时间】:2009-10-24 07:51:14
【问题描述】:
当使用索引找不到结果时,有什么方法可以禁止 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
状态变量显示更好的信息。对于 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 这样更复杂的条件则不会。
【问题讨论】:
-
我假设您对 (B, C) 对有一个索引,而不是每列单独,对吧?可能是索引统计有误,你有没有试过在表上运行
ANALYZE? -
是的,但是“索引统计信息有误”是什么意思?我不是想优化这个查询,我只是想问有没有办法禁止 MySQL 执行全表扫描。
-
查询优化器依赖于数据统计。它根据统计数据确定成本并选择最优化的方式。如果统计信息关闭,成本估算就会出错,它不会使用最佳方式获取数据。我这么说只是因为在具有新创建索引的大表上,即使查询没有返回结果,它也会使用索引。
-
@HeavyWave - Mea culpa maxima - 永远不要在即将出门时匆忙发布答案!
-
您能否发布您的表和索引定义以及查询的 EXPLAIN 输出?
标签: sql mysql query-optimization