昨天有个朋友问了我一个问题。后面经过讨论。发现这个问题还挺精髓的。可以帮助理解好几个概念。使一些理解的模棱两可的概念更清晰。值得记录下
原问题就是:
假如a,b,c三个字段建立单列索引,select a,c from tb where b=1,会回表吗?
首先结论是:会回表
引申问题:如果不想让其回表,改如何设计索引?
这个结论是:添加一个联合索引:(b,a,c)或(b,c,a) 。这两就可以利用覆盖索引,避免回表。
这两个任何一个联合索引和单例索引(b)功能重合了,可以去掉(b)
分析:(相关知识点在后面补充了。但是我觉得一般开发都具备下方的知识点) 首先是有三个个单列索引(a) (b) ( c) ,默认id才是主键索引,说明这个表上有一个主键索引id,三个非主键索引。也就是有4颗B+树。然后查询语句【select a,c from tb where b=1】 这个查询,先去(b)这棵树(非主键索引)找到对应的id。然后利用id,通过(id)这棵树(主键索引)查询出a,c,通过(id)这棵树查询a,c的过程就是回表。
这里虽然a,c分别也有索引树。但是这个查询根本没用上。(好好理解下覆盖索引的知识点和联合索引那棵树的图)
添加联合索引(b,a,c) 或(b,c,a)后。
这个查询是通过联合索引找到b=1 的叶子节点,这个时候叶子节点存储的数据是 b, a, c 还有主键。所以可以直接找到a,c数据,就不需要回表了 (这个就是覆盖索引)。
这里涉及到的知识点有:
单列索引和联合索引
聚集(聚簇)索引和非聚集索引
覆盖索引操作和回表操作
索引:Mysql数据里面,不管是MyISAM还是InnoDB存储引擎(注意存储引擎是表级的)。用的索引结构都是B+ 树。两者的区别是:MyISAM的索引和数据分开存放的,索引在MYI文件,数据在MYD文件,所以MyISAM的主键索引的B+树的叶子节点存储的是数据所在的地址。InnoDB的主键索引的B+树的叶子节点存储的是数据(InnoDB索引和数据在一个文件里)
聚集索引:另外一个名字数聚簇索引(应该是和翻译有关)。就是索引(B+树)叶子节点直接存储了数据或者直接指向数据的地址。例如MyISAM引擎存储的是直接指向数据的地址,InnoDB直接存储数据。在MySQL数据库里面,主键索引就是聚簇索引
非聚集索引 或者说叫非聚簇索引,就是索引(B+树)的叶子节点存储的是聚集索引代表的健。在MySQL里面,非主键索引就是非聚集索引。叶子节点存储的是主键。
单列索引和联合索引 : 单列索引就是(a) (b) 这种,两个索引就是(a,b)这种。
覆盖索引操作 : 就是我要查询的东西,在索引里面包含了,可以直接从索引里面取出数据
回表操作: 就是通过非主键索引进行查找的时候。如果查询的数据索引不包含。就需要根据查询出来的主键,再到主键索引查询出需要的数据
最左前缀原则 :解释总是干巴巴,网上找了一张图