为啥在这个 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 中没有使用任何键?的主要内容,如果未能解决你的问题,请参考以下文章
为啥不能修改 Mongoose 查询返回的数据(例如:findById)