1.什么是索引
索引就好比一本书的目录,所以说,就像我们看的书都有目录一样,我们建的表也都要有索引。不同之处在于:书本只有一个目录,而表可以有多个索引(但只能有一个主键索引)。
如下建表语句,在表T中,id
为主键索引,index (k)
表示设置k为一个普通索引。
create table T(
id int primary key,
k int not null,
name varchar(16),
index (k));
2.索引的结构
在MySQL的默认引擎InnoDB中,索引的结构都是B+树(B+树只有叶子结点存储数据),每一个索引都对应一个B+树,如同上表一样,主键索引id
和普通索引k
都各自对应一个B+树。不同之处在于id的B+树
的每个叶子结点中存储的是id对应的那一行的数据,而k的B+树
的每个叶子结点中存储的是该k对应的主键(id)值。
3.回表
当我们执行这一条语句时,就会发生回表:
select * from T where k=10;
执行流程如下:首先搜索k的B+树,找到的数据是k=10对应的id值,然后再根据这个id来搜索主键索引id对应的B+树
,找到该id值对应的那一行。回到主键索引搜索的过程就叫回表。
回表会降低sql语句的执行效率,如何避免回表呢?那就需要使用主键索引了:
select * from T where id=10;
使用主键索引只需搜索一次B+树就可以得到结果。
4.覆盖索引
执行如下语句,属于覆盖索引:
select id from T where k=10;
执行流程如下:首先搜索k的B+树,该树叶子结点存储的就是对应的id值,这时就不需要回表。就是说索引k中的结果覆盖了我们要查询的结果,这就是覆盖索引。
5.最左前缀原则
联合索引是由多个列组成的索引,联合索引的构造基于最左前缀原则,比如我们构造了一个(a,b,c)的联合索引,那么在B+树上叶子结点是按照a有序,a相等的情况下b有序,a和b都相等的情况下c有序的原则排列的。
(1)当我们执行一条a=1,b=2,c=3
的查询语句时,a和b都能用到索引;
(2)而当我们只通过执行b=2
的查询语句时,是用不到索引的,因为b是无序的;
(3)并且范围查询之后的字段是用不到索引的,比如我们查询a=1 and b>2 and c=3
的时候,a和b可以用到索引,而c是用不到索引的。