1.回表,简单说就是mysql内部需要经过两次查询
第一次先索引扫描,然后再通过主键去取索引中未能提供的数据。
create `table` tb_name(
`id` int(11) not null auto_increment ,
`k` int(11) default '0' ,
`name` varchar(16),
primary key(id)
index (k)
)engine=InnoDB;
我们提取id=500这一行的全部数据,这里通过主键id定位到这一行,然后返回数据
select * from T where ID=500;
+-----+---+-------+
| id | k | name |
+-----+---+-------+
| 500 | 5 | name5 |
+-----+---+-------+
这里我们先通过普通索引,搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程即为回表。
select * from T where k=5;
+-----+---+-------+
| id | k | name |
+-----+---+-------+
| 500 | 5 | name5 |
+-----+---+-------+
2.术语解释:
主键索引树的叶子节点直接就是我们要查询的整行数据,而非主键索引的叶子节点是主键的值,查到主键的值以后,还需要再通过主键的值再进行一次查询。
问题来了,刚才我们知道了主键索引查询只会查一次,而非主键索引需要回表查询多次。那么,非主键索引一定会查询多次吗?
这就轮到我们的覆盖索引登场了~~
- 覆盖索引
覆盖索引(covering index)指一个查询语句的执行只用从索引中就能够取得,不必从数据表中读取。也可以称之为实现了索引覆盖。 当一条查询语句符合覆盖索引条件时,MySQL只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后再返回表操作,减少I/O提高效率。
如,表covering_index_sample中有一个普通索引 idx_key1_key2(key1,key2)。
当我们通过SQL语句:select key2 from covering_index_sample where key1 = ‘keytest’;的时候,就可以通过覆盖索引查询,无需回表。
3.怎么判定是否出现了回表
- Extra中看到了Using where,代表是按照where条件进行了过滤,和是否走索引、回表无必然的关系。
- Extra中是using index & using where,表示select的数据在索引中能找到,但需要根据where条件过滤,这种情况也不回表。
- 只有在使用了索引,且Extra是Using where的情况下,才代表回表查询数据。