最近复习看到覆盖索引的概念,有一个 Innodb 表 user(id pk,age),id 为主键,使用 EXPLAIN SELECT id from user where id=1; 可以发现使用到了覆盖索引,但是执行 EXPLAIN SELECT age from user where id=1; 时发现 并未使用到覆盖索引,查的资料都说 InnoDB 聚集索引的叶子节点存储行记录应该包含有 age 这个字段的,但是这行查询并没有用到覆盖索引,是不是我理解有误了。
1 snappyone 2020-05-07 18:21:24 +08:00 via Android 你这个表一共就 2 列还弄啥覆盖索引 |
![]() | 2 Jacky23333 2020-05-07 18:22:28 +08:00 via Android ![]() @snappyone 老实人 |
![]() | 4 Jacky23333 2020-05-07 18:25:48 +08:00 via Android 聚集索引里面包含 age 字段跟 age 有没有加索引完全没有关系,你说的聚集索引其实只包含了 id 字段,你的 age 字段都没有索引那自然不会有索引覆盖 |
5 qmzhixu OP @Jacky23333 嗯,因为可以用到 id 找到叶节点里面的 age,按理也没有回表检索了,所以是不是覆盖索引都没区别了 |
6 qmzhixu OP @Jacky23333 只是执行计划里面的 extra 字段显示的是不是 Using index 而已 |
7 imtemp 2020-05-07 18:50:49 +08:00 覆盖索引的概念理解有差异,看看这题 https://segmentfault.com/q/1010000018998466 |
8 imtemp 2020-05-07 19:04:10 +08:00 |
9 qumingkunnan 2020-05-07 20:41:48 +08:00 via Android 索引覆盖是说通过索引查数据,然后查的数据刚好被索引包含了的意思吧?那么我理解你可以再加个字段 sex(这个字段可能加索引不太合适,只举例用),然后建立一个 age,sex 的索引,然后查询 age,sex 字段,条件用 age 或者 age,sex 。应该是满足索引覆盖的,验证下 |
10 qmzhixu OP @qumingkunnan 这种肯定是可以的,我指的是在聚集索引叶节点数据,不是其他的索引 |
11 qumingkunnan 2020-05-07 22:11:53 +08:00 via Android @qmzhixu 接我上条回复,聚簇索引通常只是主键做索引,你说的叶子节点是聚簇索引这个存储结构的一部分,不是索引。聚簇索引是 innodb 中表的存储形式,而不仅仅是索引。 |
12 gmhdbjd 2020-05-08 00:32:51 +08:00 via Android 没赚你的 id 不是真的聚集索引 |
![]() | 13 Aresxue 2020-05-08 10:11:52 +08:00 是否使用覆盖索引和 age 上面有没有索引有直接关系, 没有索引的话自然不会走覆盖索引, 而且你这个 age 还很有可能区分度 cardinality 不够或者数据量很小,CBO 发现全表扫描的 cost 反而比较小,那就直接扫全表喽 |
14 Philyu 2020-05-15 17:27:38 +08:00 age 不在索引里面,mysql 先找到索引 id=1,然后回表去找 age,当然没有索引覆盖。 |
![]() | 16 Coolha 2020-05-19 16:10:27 +08:00 An index that includes all the columns retrieved by a query. id 所构成的索引不包括 age,所以不是覆盖索引 |
17 Philyu 2020-05-19 16:13:46 +08:00 聚簇索引的一个典型例子就是主键,它直接存储数据字段,比如 id ;如果你要查 select id from xxxx where id>n 这个当然不用回表; 如果 id 是主键,另外建立了 age 的普通索引,那么 select age from xxx where id>n,是可以索引覆盖,不需要回表。 |