暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL这样的联合索引查找 一定不会走索引吗

卡二条的技术圈 2023-03-20
620
最近面试遇到这样一个问题,在一张表中有字段a
b
c
,这三个字段建立一个联合索引,使用 where b = ? and c = ?
的查询条件,是否会走到索引。
在我们常识中,是一定不会走到索引的,但实际情况是这样的吗?下面通过模拟一张表来演示这个问题。

创建模拟表

首先,我们创建一张模拟的数据表,表结构如下。
CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `age` int(11) DEFAULT '0',
  `sex` int(11) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `a` (`name`,`age`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

插入几条模拟数据。
BEGIN;
INSERT INTO `user` (`id``name``age``sex`) VALUES (1'1'01);
INSERT INTO `user` (`id``name``age``sex`) VALUES (2'1'01);
INSERT INTO `user` (`id``name``age``sex`) VALUES (3'1'01);
INSERT INTO `user` (`id``name``age``sex`) VALUES (4'1'01);
INSERT INTO `user` (`id``name``age``sex`) VALUES (5'2'01);
COMMIT;

测试查询

上面做好了数据准备,接下来,我们执行一组SQL语句,使用 explain
打印结果查看一下。
1、直接查询全部数据
explain select * from `user`;

explain
执行结果。
***************************[ 1. row ]***************************
id            | 1
select_type   | SIMPLE
table         | user
partitions    | <null>
type          | ALL
possible_keys | <null>
key           | <null>
key_len       | <null>
ref           | <null>
rows          | 5
filtered      | 100.0
Extra         | <null>

通过上面的测试,发现是进行了全表扫描。这是因为,我们进行了查询全部字段,虽然 id
(name, age)
都有建立索引,但是 select * from
user语句中的 "*" 要求查询到
age 字段,
age` 字段在既没有建立索引,也没有在索引树上。要查询该字段,还需要进行全表扫描。
2、 使用 where
条件字段查询
explain select id,age from `user` where age = 0;

上面的查询语句,直接查看是没有走到索引的,同样使用 explain
语句打印一下执行结果。
***************************[ 1. row ]***************************
id            | 1
select_type   | SIMPLE
table         | user
partitions    | <null>
type          | index
possible_keys | a
key           | a
key_len       | 1027
ref           | <null>
rows          | 5
filtered      | 20.0
Extra         | Using where; Using index

通过上面的 type
字段,可以很明显的看到,使用了 index
类型的查询。

index 字段说明

在官方文档中,关于 index
字段,有这样一段说明。
The index join type is the same as ALL, except that the index tree is scanned. This occurs two ways:
1、If the index is a covering index for the queries and can be used to satisfy all data required from the table, only the index tree is scanned. In this case, the Extra column says Using index. An index-only scan usually is faster than ALL because the size of the index usually is smaller than the table data.
2、A full table scan is performed using reads from the index to look up data rows in index order. Uses index does not appear in the Extra column.
MySQL can use this join type when the query uses only columns that are part of a single index.
这段话是什么意思呢?大致描述的是,index
类型的查询与 ALL
查询是相同,不同之处在于 扫描索引树
,也就是说,还是走到了索引,只不过是全盘扫描索引树,然后在进行磁盘查找。
如果索引是查询的覆盖索引,并且可用于满足表中,仅扫描索引树。换句话说,使用覆盖索引,会比 ALL
查询效果高,这是因为直接在索引树中就查询到数据了。

总结

select查询的 type
类型,并不是完全不走索引的,如果 type
字段是 ALL
则走的全表扫描;如果是 index
则会进行索引树扫描,然后再全盘扫描,这种情况仍然是走到索引了。


文章转载自卡二条的技术圈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论