【问题标题】:MySQL explain outputMySQL解释输出
【发布时间】:2012-02-17 16:10:43
【问题描述】:

有谁知道

使用索引

在哪里使用;使用索引

在 mysql 的解释输出中(在 Extra 中)?

复制:

CREATE TABLE `tmp_t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) NOT NULL DEFAULT '0',
  `b` varchar(50) CHARACTER SET latin1 NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `k1` (`a`),
  KEY `k2` (`b`)
) ENGINE=InnoDB AUTO_INCREMENT=5;

insert into tmp_t1 (a,b) values (1,'b1'), (1, 'b2'), (2, 'b3');

mysql> 解释 select count(1) from tmp_t1 where a=1 \G

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tmp_t1
         type: ref
possible_keys: k2,kz
          key: kz
      key_len: 4
          ref: const
         rows: 3
        Extra: Using index
1 row in set (0.11 sec)

mysql> 解释 select count(1) from tmp_t1 where b='b1' \G

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tmp_t1
         type: ref
possible_keys: k3
          key: k3
      key_len: 52
          ref: const
         rows: 2
        Extra: Using where; Using index
1 row in set (0.00 sec)

有谁知道为什么在第一种情况下额外字段中只有“使用索引”,而在第二种情况下是“使用 where;使用索引”? 案例之间的区别在于,第一个案例在整数上运行 WHERE,而第二个案例在 varchar(50) 字段上执行。 但是这有什么关系呢??

感谢您的帮助!

【问题讨论】:

  • using where 表示您的 SQL 中有一个过滤器(= WHERE 子句)。 using index 表示查询使用索引。两者都是不同的东西。我不明白这个问题。
  • 问题是为什么mysql只使用索引来执行第一个查询,而执行第二个查询时会报告“使用where”。我之所以这么问,是因为我无法理解这两个查询之间的区别——一个在 where 条件中使用整数,另一个是 varchar 字段这一事实如何影响 mysql 执行它们的方式(为什么第二个查询不使用“仅索引”?)
  • 第一个 EXPLAIN 中提到并实际使用的kz 索引是什么?
  • 现在编辑后您的问题更有意义。但 SHOW CREATE TABLE 与您的 EXPLAIN SELECT 语句不匹配。您的 EXPLAIN 中有键“k3”和“kz”,但 CREATE TABLE 中没有。我想您的问题是我们看不到的,因为您没有发布相关部分。
  • 使用“WHERE a = 1”时,您的第一个解释的“rows: 3”也与您的示例数据不匹配......您只有 2 行。 (类似于第二个解释,它说 2 行,但示例中只有 1 行)

标签: mysql explain


【解决方案1】:

我应该确认这种差异确实非常令人困惑。在其他情况下,Using where; Using index 可能意味着该索引已被使用但已被完全扫描。就像您在 (a, c) 上有一个复合索引但进行类似 SELECT a FROM thetable WHERE c = 1 的查询一样。在这种情况下,MySQL 将使用索引(因为它包含所有必要的数据并且在内存中),但会通过索引进行全面扫描。

结果你应该看到变量在

SHOW STATUS LIKE 'Handler_read_next';

将增加到表中的行数。

但查询不是这样:

select count(*) from tmp_t1 where b='b1';

它检查索引中的确切行数。我认为这是某种错误或功能,又一个证据表明结果 EXPLAIN 本身并没有什么可依赖的。有趣的是,对于较大表和复合索引的查询,其中 VARCHAR 是索引EXPLAIN 中的第二个,有时不会显示Using where。我很困惑。

【讨论】:

  • 感谢您介绍Handler_read_* 状态变量的世界。
【解决方案2】:

“使用索引”表示只使用索引进行实际查询(查找要返回的行),这意味着mysql不需要读取实际行。

仅使用从表中检索列信息 索引树中的信息,无需进行额外的查找 读取实际行。查询使用时可以使用此策略 仅属于单个索引的列。

“使用where”表示在进行数据查找时也使用索引(对于它需要返回的行,找到你选择的列对应的数据)

如果 Extra 列也显示 Using where,则表示索引正在 用于执行键值的查找。如果不使用 where,则 优化器可能正在读取索引以避免读取数据行但不是 使用它进行查找。例如,如果索引是覆盖索引 对于查询,优化器可能会扫描它而不使用它进行查找。

Source in mysql's documentation(搜索“使用索引”)

【讨论】:

    【解决方案3】:

    在哪里使用

    WHERE 表达式(除了可能的键查找之外)用于检查该行是否应该被接受。如果您没有 'Using where' 和 ALL 的连接类型,那么您可能做错了!

    使用索引

    只有索引用于从表中检索所需的信息。无需执行额外的查找来检索实际记录。

    【讨论】:

    • 我没有 JOIN,只有一个简单的 where 条件(我在上面的原始问题中添加了架构和 sql 命令)。
    • 那么只有第一部分适用于您的 EXPLAIN 输出,即 WHERE 表达式(除了可能的键查找之外)用于检查是否应接受该行。
    猜你喜欢
    • 2012-12-17
    • 2023-03-18
    • 2012-05-19
    • 2014-02-17
    • 2011-05-03
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多