【问题标题】:Mysql Incorrect optimiser workMysql 不正确的优化器工作
【发布时间】:2017-08-15 18:59:12
【问题描述】:

我有下一个 innodb 表:

CREATE TABLE events (
  id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  server int(11) UNSIGNED NOT NULL,
  internal_id bigint(20) UNSIGNED NOT NULL,
  pid int(11) UNSIGNED NOT NULL,
  event_datetime DATETIME NOT NULL,
  event_stamp int(11) NOT NULL,
  status tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
  PRIMARY KEY (id),
  INDEX IDX_events (event_stamp, pid),
  INDEX IDX_events2 (event_stamp),
  UNIQUE INDEX UK_events_hash (internal_id, server)
)
ENGINE = INNODB;

记录数为 ~ 5 百万。当我执行下一条 SQL 时:

EXPLAIN SELECT SQL_NO_CACHE id, internal_id, pid, status FROM events WHERE event_stamp BETWEEN UNIX_TIMESTAMP('2017-01-01') AND UNIX_TIMESTAMP(CURDATE());

Profiler 说有 2 个可能的索引,但没有使用。总执行时间为 0.105 毫秒。然后我添加“FORCE INDEX (IDX_events2)”,分析器说使用了索引,总执行时间为 0.02 毫秒。

那么为什么优化器认为不使用 index 并遍历大约 200 万条记录比使用 index 更快?使用索引执行得更快,而且合乎逻辑。

解释输出:
1 SIMPLE c (null) ALL IDX_events,IDX_events2 (null) (null) (null) 5944539 50 Using where

并且用力:
1 SIMPLE c (null) range IDX_events2 IDX_events2 4 (null) 2972269 100 Using index condition

【问题讨论】:

  • 除非我误解:0.105ms 比 0.020ms 长。
  • 是的,我不明白为什么优化器不使用索引。使用力指数更快
  • 为我们提供有力和不强大的解释
  • @Noob 好的,我在问题中添加了解释输出。
  • @hadwin 请不仅提供输出,还提供整个查询和输出

标签: mysql percona


【解决方案1】:

大多数数据库使用B树进行索引。在这种情况下,数据库优化器不使用索引,因为它在没有索引的情况下扫描速度更快

2mil / 5mil > 20%,我猜做表扫描比使用索引更快。索引并不总是最好的解决方案Avoid full table scan

当 MySQL 使用 全表扫描以解决查询。这通常发生在 以下条件:

您正在使用低基数的键(许多行与键匹配 值)通过另一列。在这种情况下,MySQL 假设由 使用密钥它可能会进行许多密钥查找和一个表 扫描会更快。

在您的查询中使用范围运算符。在大多数情况下,它可以更快地避免索引扫描。当您创建索引时,扫描索引页面以查找匹配项的成本更高。

【讨论】:

  • 是的,我明白了。但实际执行表明,使用索引强制执行速度要快得多(不使用索引为 105 毫秒,使用强制为 20 毫秒 - 速度快 400%)。所以我不明白为什么优化器认为表扫描更快
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
  • 1970-01-01
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多