我遇到了一个问题,mysql 5.6 没有使用索引并导致非常慢的查询。
- 具有以下字段的命名人员的表:id、group_id、city_id、...
- 应该可用于group_id的索引:(group_id、city_id(
查询为:
SELECT people.* FROM people WHERE people.group_id = 12345 ORDER BY people.id ASC LIMIT 10 OFFSET 0;
此查询的 EXPLAIN 显示它不使用索引并扫描 9324 行:
possible_keys: index_people_on_group_id_and_city_id
key: PRIMARY
rows: 9324
extra: Using where
但是,我的慢查询日志显示检查的行很大:
Query_time: 16.254633 Lock_time: 0.000038 Rows_sent: 10 Rows_examined: 7429457
- 为什么不使用索引?
- 为什么优化器如此错误?我是否需要以某种方式重建元数据,以便它意识到它必须扫描超过 9324 行,然后才能做出更好的选择?
我不知道数字9324是从哪里来的。group_id 12345 有超过 10k 条记录。
编辑:我发现限制的大小在这里很重要。限制为 100 时,它使用密钥。限制为 10 时,它错误地认为它必须扫描 9324 行。限制为 1 时,它错误地认为它必须扫描 932 行。
我发现这可能是MySQL 5.7.6中修复的错误的结果。
- 发行说明 (https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-6.html(
- 错误:https://bugs.mysql.com/bug.php?id=73837
对于将 ORDER BY 与 LIMIT 组合在一起的查询,优化程序可能会切换 到适用于 ORDER BY 的索引。在某些情况下,决定 转换是基于启发式而不是成本。优化器 现在统一决定是否在成本基础上切换。 这应该会导致更好的性能,当切换会导致 用于读取整个索引或其中大部分以查找的查询 限定行。