MySQL比较常见的三种存储引擎:InnoDB、MyISAM、Memory。
这三种引擎实现索引的方式不太相同,InnoDB、MyISAM使用的是B+树,Memory使用的是哈希索引。虽然InnoDB、MyISAM都使用的是B+树,但两者还是不完全相同的。InnoDB中,主键索引的B+树叶子节点存储的是整行数据。MyISAM主键索引的B+树叶子节点存储的是整行数据所在内存中的地址。
回表&覆盖索引:
用一个简单的例子来说明。创建一张表emp,如下图。
给ename创建普通索引,这张表一共有两个索引,如下图。
下面是两个不同的sql语句的执行计划:
两条sql语句的区别就是一条select *另外一个是select empno。
先解释一下select * from emp where e.ename='test';先是根据ename列的索引B+树,找到叶子节点上存储的主键值,然后根据主键的索引B+树,查找整行的数据。整个这个操作叫做回表。
再来说一下select empno from emp where e.ename='test';先是根据ename列的索引B+树,找到叶子节点上存储的主键值,由于显示的就是empno,不需要再去主键的索引B+树去查找了,这种情况叫做覆盖索引。
通过上面两个例子,可以看出来回表操作需要遍历两次B+树,增加了IO次数。所以能用覆盖索引就尽量用覆盖索引。
简单补充一下,上图的执行计划中的Extra 可能会出现using where、using index、using index;using where、using index contion、null。如果出现了using index,就表示覆盖索引。