MySQL使用查询排序做出糟糕的优化选择,并且解释不正确



我遇到了一个问题,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
  1. 为什么不使用索引?
  2. 为什么优化器如此错误?我是否需要以某种方式重建元数据,以便它意识到它必须扫描超过 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 的索引。在某些情况下,决定 转换是基于启发式而不是成本。优化器 现在统一决定是否在成本基础上切换。 这应该会导致更好的性能,当切换会导致 用于读取整个索引或其中大部分以查找的查询 限定行。

最新更新