为啥在这个 EXPLAIN 中没有使用任何键?

Posted

技术标签:

【中文标题】为啥在这个 EXPLAIN 中没有使用任何键?【英文标题】:Why are no keys used in this EXPLAIN?为什么在这个 EXPLAIN 中没有使用任何键? 【发布时间】:2016-09-09 20:57:41 【问题描述】:

我希望这个查询使用一个键。

mysql> DESCRIBE TABLE Foo;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | bigint(20)  | NO   | PRI | NULL    | auto_increment |
| name  | varchar(50) | NO   | UNI | NULL    |                |
+-------+-------------+------+-----+---------+----------------+

mysql> EXPLAIN SELECT id FROM Foo WHERE name='foo';
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                                               |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE noticed after reading const tables |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+

Foo 在name 上有一个唯一索引,那么为什么SELECT 中没有使用该索引?

【问题讨论】:

因为WHERE 总是返回false。它在文档中.. 另外,让我猜一下,您的表中没有与foo 匹配的记录。 MySQL 不会为小表使用索引,因为它会招致 I/O 损失而没有收益。不遍历索引就可以断定没有这样的记录。 dba.stackexchange.com/a/21265 【参考方案1】:

来自题为EXPLAIN Output Format的MySQL手册页:

Impossible WHERE 在阅读 const tables 后注意到(JSON 属性: 留言)

MySQL 已读取所有 const(和系统)表并注意到 WHERE 子句总是假的。

以及const表的定义,来自标题为Constants and Constant Tables的Page:

MySQL 常量不仅仅是查询中的文字。 也可以是常量表的内容,定义为 如下:

零行或只有一行的表

受 WHERE 条件限制的表表达式, 包含 column = constant 形式的表达式,对于所有 表的主键的列,或任何一个的所有列 表的唯一键(前提是唯一列也是 定义为 NOT NULL)。

第二个参考是一页半长。请参考。

const

常量

该表最多有一个匹配行,在开始时读取 查询。因为只有一行,所以列中的值 该行可以被优化器的其余部分视为常量。 const 表非常快,因为它们只被读取一次。

const 用于比较 PRIMARY KEY 或 UNIQUE 的所有部分 常数值的索引。在以下查询中,tbl_name 可以是 用作 const 表:

SELECT * FROM tbl_name WHERE primary_key=1;

SELECT * FROM tbl_name WHERE primary_key_part1=1 AND primary_key_part2=2;

【讨论】:

TL;DR 尝试where name!='foo' 以防止选择被视为微不足道的单行值【参考方案2】:

可能是因为该表Foo 的数据量非常少。在这种情况下,优化器会选择进行表扫描而不是通过索引查看。

正如MySQL Documentation 所说的那样

索引对于小表或大表的查询不太重要 报表查询处理大部分或所有行的位置。当一个查询 需要访问大部分行,顺序读取比 通过索引工作。顺序读取最小化磁盘寻道,甚至 如果查询不需要所有行。

【讨论】:

这是一个不同的问题。您描述的问题是针对小表或高基数情况 @Drew,是的,但有可能,大多数情况下这就是原因,除非指定的 WHERE 条件最终没有返回任何记录。 我将生成一个示例/imgur 链接以在说明中显示标准输出以供您参考。编辑:给你,这是你的情况i.imgur.com/oGc0hsw.jpg

以上是关于为啥在这个 EXPLAIN 中没有使用任何键?的主要内容,如果未能解决你的问题,请参考以下文章

为啥没有聚合的结束 Group By 会减慢我的查询速度?

explain是啥意思

为啥不能修改 Mongoose 查询返回的数据(例如:findById)

为啥 MySQL 不使用 EXPLAIN 中的索引?

mysql数据库的一个表字段为explain,一查询这个字段就报错!

explain结果总结