mysql避免回表问题

避免回表问题__

mysql数据库 innodb

CREATE TABLE `abc_innodb`
(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a`  int(11)     DEFAULT NULL,
  `b`  int(11)     DEFAULT NULL,
  `c`  varchar(10) DEFAULT NULL,
  `d`  varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_abc` (`a`, `b`, `c`)
) ENGINE = InnoDB;

可以通过创建联合索引,索引覆盖的方式避免回表
问题1: 联合索引页字节点储存的是主键,是怎么避免回表的? 难道叶子结点还存 索引列数据?

select a, b from abc_innodb where a = 1 and b = 2 and c= 3;

CREATE TABLE `user_innodb`
(
  `id`       int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) DEFAULT NULL,
  `age`      int(11)     DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_age` (`age`) USING BTREE
) ENGINE = InnoDB;

问题2: 表中一列创建普通索引, 查询结果就是就是索引列,是否可以避免回表 ?

select age from abc_innodb where age = 1 ;

问题1:在索引中其实也是存了索引数据的,在你的idx_abc这个索引里,是包含了a、b、c三个字段的信息,因此在select的时候,可以直接从索引文件中查找到值直接返回即可,不需要回到表中去查询,如果此时再在一个不在索引中的e列,就需要回到表中去检索,然后将结果合并返回。
问题2:凡是索引中有数据的,都不会回表查询。

希望可以帮助你。

问题一:
你可以这么理解,索引是为了快速检索数据用的,那么你需要用来检索的信息,都会展示在索引中。
例:
| 非叶子节点 | 叶子节点 |
| ------ | ------ |
| a1,b1,c1 | id1 |
| a2,b2,c2 | id2 |
| a3,b3,c3 | id3 |
| a4,b4,c4 | id4 |

你查询结果与查询条件只包含 a,b,c列,这三列在联合索引的非叶子节点中都有,为什么还要通过id,再去进行查询?是不是多此一举。

问题二:
同上,回表的目标是为了查询那些当前条件下无法查询到的字段(这也是为什么建议查询字段不要写 “*” 的原因)。

联系索引使用最左的字段来构建B+tree ,所以联合索引会有最左前缀匹配原则,B+tree的data部分存储的是联合索引所在行的主键值,比如说建立了(A,B)索引,因为叶子节点是线性排列的,所以在A值相等的情况下,B值又是按顺序排列的,但是这种顺序是相对局部的,所以在最左匹配原则下遇到范围查询就会停止,剩下的字段都无法使用索引,也就不会存在回表的情况了。
普通索引如果查询索引中有数据,就不会发生回表查询