为什么在mysql中使用多列索引的第二列时mysql仍然使用索引来获取数据?
我们知道mysql使用最左边的匹配规则,但是这里我没有使用第一个col,而是使用了第二个col,下面的两个select
操作结果表明mysql有时使用索引,有时不使用索引。为什么?另外,我的mysql版本是5.6.17。
1。创建表:
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`cid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name_cid_INX` (`name`,`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8
2.run select
:
EXPLAIN SELECT * FROM student WHERE cid=1;
3。结果: Result with index
它表明mysql使用索引获取数据。
下面是另一个表。
1。创建表:
CREATE TABLE `test_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
`address` varchar(45) DEFAULT NULL,
`phone` varchar(45) DEFAULT NULL,
`note` varchar(45) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `NAME` (`name`),
KEY `AGE` (`age`),
KEY `LeftMostPreFix` (`name`,`address`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
2.run select
:
explain SELECT * FROM test.test_table where address = '东京'
3。结果: Result without index
相反,这里表明mysql没有使用索引来获取数据。
比较上面两个结果,我感到困惑,为什么第一个结果使用的索引是最左边的匹配规则。
答案 0 :(得分:1)
键可能会命名可能索引值中不存在的索引。如果没有任何可能的索引索引适合于查找行,但是查询选择的所有列都是其他索引的列,则可能发生这种情况。也就是说,命名索引覆盖了选定的列,因此尽管不使用索引来确定要检索的行,但索引扫描比数据行扫描更有效。
因此,尽管这里使用了一个键,但实际上并没有正常使用它。在某些情况下(使用第一个示例)将其用作表扫描仍然更加有效,在其他情况下(在第二个示例中)
大多数情况下,这些事情是由优化程序根据几件事(表的使用等)决定的。
最好记住的是,这里不能“使用索引”,这就是possible keys
中没有索引的原因。如果第一列在其中,则只能使用索引。
答案 1 :(得分:0)
在任何情况下,两个索引都不以WHERE
中的索引开头,因此将对表或索引进行全面扫描。
情况1:索引是“覆盖”的,因此,它是哪种比较好(表扫描还是索引扫描)。优化器恰好选择了二级索引。 EXPLAIN FORMAT=JSON SELECT ...
可能有足够的细节来解释这种情况下的“为什么”。
情况2:由于*
(在SELECT *
中),辅助索引处于不利地位-它不是“覆盖”的,因此处理将在索引和索引之间来回反弹。数据。因此,最好只扫描表格。
而不是试图理解EXPLAIN(在这种情况下),将问题转过来:“针对此表的此查询的最佳索引是什么?”然后遵循准则here。