MySQL explain输出

4

有人知道在mysql的explain输出(Extra字段)中

使用Index

使用where; 使用index

有什么区别吗?

问题再现:

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> 解释选择计算 tmp_t1 表中 a=1 的数据量 \G

(注意:保留了HTML标签)
*************************** 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> 解释选择计算 tmp_t1 表中 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” 表示查询使用了索引。这两个概念是不同的。我不明白问题所在。 - Kaii
问题在于为什么MySQL仅使用索引来执行查询1,而对于查询2的执行却报告“使用where”。我问这个问题是因为我无法理解这两个查询之间的区别 - 一个使用整数作为where条件,另一个使用varchar字段如何影响MySQL执行它们的方式(为什么第二个查询不使用“仅索引”?) - Zaar Hai
第一个EXPLAIN中提到并实际使用的kz索引是什么? - newtover
现在在编辑后,你的问题更有意义了。但是SHOW CREATE TABLE与你的EXPLAIN SELECT语句不匹配。你的EXPLAIN中有"k3"和"kz"键,但在你的CREATE TABLE中却没有。我猜你的问题可能是我们看不到的,因为你没有发布相关部分。 - Kaii
你的第一个解释中的“行数:3”与使用“WHERE a = 1”时的示例数据不匹配...你只有2行。第二个解释也类似,它说有2行,但示例中只有1行。 - Kaii
如果你使用 COUNT(a) 或者 COUNT(b) 而不是 COUNT(1),会发生什么? - Kaii
3个回答

3
我应该确认这个差异确实非常令人困惑。在其他情况下,“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_*状态变量的世界。 - Zaar Hai

0

使用Where

WHERE表达式(除了可能的键查找)用于检查是否应接受该行。如果您没有将“Using where”与ALL连接类型一起使用,则可能做错了什么!

使用索引

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


我没有JOIN,只有一个简单的where条件(我已经在上面的原始问题中添加了模式和SQL命令)。 - Zaar Hai
只有第一部分适用于您的EXPLAIN输出,即:除了可能的键查找之外,还使用WHERE表达式来检查是否应接受该行。 - Mahesh Patil

0
“使用索引”意味着只有索引用于执行实际查询(查找要返回的行),这意味着MySQL不需要读取实际行。

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

“使用where”表示在执行数据查找时也使用索引(对于需要返回的行,查找所选列的相应数据)

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

mysql文档中的来源(搜索“using index”)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接