为啥mysql解释说'使用索引'而使用的索引不包含必填字段
Posted
技术标签:
【中文标题】为啥mysql解释说\'使用索引\'而使用的索引不包含必填字段【英文标题】:why mysql explain says 'using index' while the index used do not contain required fields为什么mysql解释说'使用索引'而使用的索引不包含必填字段 【发布时间】:2016-06-08 03:30:08 【问题描述】:这是 mysql(innodb) 中解释命令的输出:
explain select * from multi_index_test_tbl_1 force index(`query_index_1`) where `text_field1`='0' order by `numeric_field2` desc limit 1000000;
+----+-------------+------------------------+------+---------------+---------------+---------+-------+----------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------------+------+---------------+---------------+---------+-------+----------+--------------------------+
| 1 | SIMPLE | multi_index_test_tbl_1 | ref | query_index_1 | query_index_1 | 386 | const | 53547628 | Using where; Using index |
+----+-------------+------------------------+------+---------------+---------------+---------+-------+----------+--------------------------+
表multi_index_test_tbl_1
的架构如下:
CREATE TABLE IF NOT EXISTS `multi_index_test_tbl_1`
(
`text_field1` varchar(128) NOT NULL,
`numeric_field1` float NOT NULL,
`numeric_field2` float NOT NULL,
`text_field2` varchar(128) NOT NULL,
PRIMARY KEY (`text_field1`,`numeric_field1`,`text_field2`),
KEY `query_index_1` (`text_field1`,`numeric_field2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
似乎使用了query_index_1
。并且“使用索引”出现在Extra
中,而索引query_index_1
不包含表multi_index_test_tbl_1
中的所有字段。
因为 mysql 文档是这样说的:
使用索引(JSON 属性:using_index)
仅使用索引树中的信息从表中检索列信息,而无需进行额外的查找以读取实际行。当查询仅使用属于单个索引的列时,可以使用此策略。
我很困惑这里到底发生了什么。
【问题讨论】:
@zerkms mysql 文档说using index
表示使用only information in the index
检索列
为什么不显示表架构?你为什么要强制索引然后想知道为什么它说“好的,我会使用那个索引”
@Drew 抱歉,我已经添加了架构。但问题是:根据官方文档,using index
不仅表示使用了索引,还表示没有使用实际行(因此是聚集索引)。
您意识到explain
返回的信息中有一半有时是边缘幻想之地。您要求例行程序在一瞬间将信息返回给我们不耐烦的消费者。并在那一瞬间确定其所谓的计划。它可以在实际运行时愉快地偏离。并且该执行可能需要长达 10 个小时才能运行(当不使用 explain
但实际运行时)。
【参考方案1】:
啊,但它确实“包含必填字段”。详细说明...
InnoDB 在每个“二级”索引中包含PRIMARY KEY
的所有列。所以,
KEY `query_index_1` (`text_field1`,`numeric_field2`)
真的更像
KEY `query_index_1` (`text_field1`,`numeric_field2`,
`numeric_field1`,`text_field2`)
在您的示例中,这包括所有列。因此,SELECT
中的所有内容,包括*
,都可以在该二级索引中找到。所以,“使用索引”是“正确的”。
这是 InnoDB 有时优于 MyISAM 的一种方式。
请尝试EXPLAIN FORMAT=JSON SELECT ...
了解更多详情。
【讨论】:
这就是答案!我已经通过一些测试表的实验证实了这一点。以上是关于为啥mysql解释说'使用索引'而使用的索引不包含必填字段的主要内容,如果未能解决你的问题,请参考以下文章