为什么在mysql中使用多列索引的第二列时mysql仍然使用索引来获取数据?

时间:2018-08-02 07:08:27

标签: mysql indexing

为什么在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没有使用索引来获取数据。

比较上面两个结果,我感到困惑,为什么第一个结果使用的索引是最左边的匹配规则。

2 个答案:

答案 0 :(得分:1)

mysql manual

  

键可能会命名可能索引值中不存在的索引。如果没有任何可能的索引索引适合于查找行,但是查询选择的所有列都是其他索引的列,则可能发生这种情况。也就是说,命名索引覆盖了选定的列,因此尽管不使用索引来确定要检索的行,但索引扫描比数据行扫描更有效。

因此,尽管这里使用了一个键,但实际上并没有正常使用它。在某些情况下(使用第一个示例)将其用作表扫描仍然更加有效,在其他情况下(在第二个示例中)

大多数情况下,这些事情是由优化程序根据几件事(表的使用等)决定的。

最好记住的是,这里不能“使用索引”,这就是possible keys中没有索引的原因。如果第一列在其中,则只能使用索引。

答案 1 :(得分:0)

在任何情况下,两个索引都不以WHERE中的索引开头,因此将对表或索引进行全面扫描。

情况1:索引是“覆盖”的,因此,它是哪种比较好(表扫描还是索引扫描)。优化器恰好选择了二级索引。 EXPLAIN FORMAT=JSON SELECT ... 可能有足够的细节来解释这种情况下的“为什么”。

情况2:由于*(在SELECT *中),辅助索引处于不利地位-它不是“覆盖”的,因此处理将在索引和索引之间来回反弹。数据。因此,最好只扫描表格。

而不是试图理解EXPLAIN(在这种情况下),将问题转过来:“针对此表的此查询的最佳索引是什么?”然后遵循准则here