什么是回表查询?
一般情况下是:先到普通索引上定位主键值,再到聚集索引上定位行记录,它的性能较扫一遍索引树低。
具体解释:
我们自己建的索引不管是单列索引还是联合索引,都称为普通索引,主键索引是聚簇索引,也就是索引的叶子节点存的是整个单条记录的所有字段值。每个普通索引就对应着一颗独立的索引B+树,索引 B+ 树的节点仅仅包含了索引里的几个字段的值以及主键值。当你执行一条sql语句时,需要从两个b+索引中去取数据。
在什么情况会出现回表操作?
举个例子:
表tbl
有a,b,c
三个字段,其中 a
是主键,b
上建了索引,然后编写sql语句SELECT * FROM tbl WHERE a=1
这样不会产生回表,因为所有的数据在a的索引树
中均能找到;
如果是SELECT * FROM tbl WHERE b=1
这样就会产生回表,因为where条件是b
字段,那么会去b的索引树
里查找数据,但b
的索引里面只有a,b
两个字段的值,没有c
,那么这个查询为了取到c
字段,就要取出主键a
的值,然后去a
的索引树去找c
字段的数据。查了两个索引树,就出现了回表操作。
什么是索引覆盖?
简单说就是, 索引列+主键 包含 SELECT 到 FROM之间查询的列 。就是索引覆盖。可以不用去进行回表操作。
为什么设置了命中了索引但还是造成了全表扫描
就是虽然命中了索引,但在叶子节点查询到记录后还要大量的回表,优化器认为不如直接去扫描全表。