有两种索引, 聚簇索引 和 非聚簇索引 。
假设我们有表tabA,字段:
id(主键自增),name,address
其中主键id采用的就是聚簇索引。
如果我们将name设为索引:
ALTER TABLE tabA ADD INDEX (name);
则为非聚簇索引。
聚簇索引与非聚簇索引虽然都是B+树结构,但是区别在于:
聚簇索引节点存储的是主键,在叶子节点上存储行记录。
而非聚簇索引存储的是name,在叶子节点上存储的是对应的主键。
所以当我们查询name的记录时:
SELECT * FROM tabA WHERE name='leo';
先去name的非聚簇索引,找到叶子节点上的id,再去聚簇索引通过id查到对应的记录。
要过两次索引树,性能相对更低,这就是回表查询。
覆盖索引是指如果能在一颗索引树上取得所有信息,那么就不需要进行回表查询了。
假设我们查询语句如下:
SELECT id,name FROM tabA WHERE name='leo';
无论是要select的name、id,还是where的name都在非聚簇索引内,遍历一次就能拿到所有数据,就无需回表查询了。
如果是:
SELECT id,name,address FROM tabA WHERE name='leo';
因为address不在聚簇索引上,所以还是需要回表查询。
当然,如果我们创建了name、address的联合索引,也不会回表查询了:
ALTER TABLE tabA ADD INDEX (name,address);
通过explain要执行的SQL语句,我们可以看Extra字段,如果有“Using index”,就说明用到了索引覆盖。