避免回表问题__
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值又是按顺序排列的,但是这种顺序是相对局部的,所以在最左匹配原则下遇到范围查询就会停止,剩下的字段都无法使用索引,也就不会存在回表的情况了。
普通索引如果查询索引中有数据,就不会发生回表查询