student表
InnoDB的主键和二级索引树
场景一:uid是主键
select * from student;
搜索的是整个索引树,构建的下面这个索引树是主键索引树
select * from student where uid=5;
等值查询,从根节点开始,按照二分搜索的方式值搜到根节点上找到这个5,就找到5所对应这一行的数据了。
select * from student where uid<5;
范围查询,不需要在B+树上做范围查询,找uid<5的那些节点,直接在有序链表搜索就行,找第一个uid>=5的,就找到了满足uid<5的那些数据。
select * from student where name='linfeng';
name没有主键,需要整表搜索,直接搜有序链表,效率慢。
场景二:uid是主键,name创建了普通索引(二级索引)
构建的是辅助索引树/二级索引树,二级索引树,key当然是二级索引的字段name,data是所在记录行的主键uid值。
select name from student where name='linfeng';
过滤字段是name,有索引,就在二级索引树上等值匹配linfeng,因为select只有name,所以在这个二级索引树上linfeng就可以找到。
select uid,name from student where name='linfeng';
找name构建的二级索引树,因为二级索引树存的本身存的key就是name,值就是它所在行的主键,也就是说搜索这个二级索引树可以得到这两个字段的值
select * from student where name='linfeng';
搜索name的二级索引树,可以找到linfeng但是select的是*,不仅需要uid还需要name、age和sex,而这个二级索引树上并没有存name和sex,所以需要回表
所以对于这种情况,业务上如果只需要name或者是uid和name,就不要去写成*了,因为写成select *,为了去取uid和name之外的值需要回表,回表就意味着更多的搜索和更多的磁盘I/O,效率低!所以select的时候需要考虑需要哪些字段,不要什么情况下都写成 *。
不行,如果只有age创建索引,会有Using filesort。
优化后还是使用到了外部排序,有的人想可以给name加索引,但是一次sql的执行,一张表只能用到一个索引,搜索了这个字段的索引树就不会搜索另一个字段的索引树了,这样会太慢了,因为加载索引也是要耗费磁盘I/O!
key存放age+name,也就是多列索引(联合索引)。先按age排序,再按name排序,age相同,按name进行排序。
在这个二级索引树上搜索的时候,先搜到age=20有好多个。因为它本身构建这个B+树的时候就是age相等的情况下name已经排好序了,所以这里面不需要再using filesort对name进行排序了。
不能用到多列索引,因为现在是以name和age创建的索引,所以在B+树上先按age排序再按name排序,如果只拿name作为过滤的话,在这个B+树上就没有办法匹配。所以多列索引使用的时候一定要使用到第一个列
MyISAM的主键索引树和二级索引树
场景:uid主键,name二级索引
MyISAM下的主键索引树和二级索引树没有区别,唯一的区别就是主键索引树主键是不能重复的,而二级索引树这个普通索引是可以重复的,除此之外,存储方式一模一样。
数据和索引没在一块放叫做非聚集索引,索引和数据都在主键索引树上放的叫聚集索引。
MyISAM就不涉及回表操作了!