InnoDB和MyISAM的主键索引树、二级索引树

183 阅读3分钟

student表 image.png

InnoDB的主键和二级索引树

场景一:uid是主键

select * from student;搜索的是整个索引树,构建的下面这个索引树是主键索引树

image.png

select * from student where uid=5;等值查询,从根节点开始,按照二分搜索的方式值搜到根节点上找到这个5,就找到5所对应这一行的数据了。

select * from student where uid<5;范围查询,不需要在B+树上做范围查询,找uid<5的那些节点,直接在有序链表搜索就行,找第一个uid>=5的,就找到了满足uid<5的那些数据。

image.png

select * from student where name='linfeng';name没有主键,需要整表搜索,直接搜有序链表,效率慢。

image.png

场景二:uid是主键,name创建了普通索引(二级索引)

构建的是辅助索引树/二级索引树,二级索引树,key当然是二级索引的字段name,data是所在记录行的主键uid值。

image.png 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,所以需要回表 image.png image.png 所以对于这种情况,业务上如果只需要name或者是uid和name,就不要去写成*了,因为写成select *,为了去取uid和name之外的值需要回表,回表就意味着更多的搜索和更多的磁盘I/O,效率低!所以select的时候需要考虑需要哪些字段,不要什么情况下都写成 *。

image.png 不行,如果只有age创建索引,会有Using filesort。 image.png 优化后还是使用到了外部排序,有的人想可以给name加索引,但是一次sql的执行,一张表只能用到一个索引,搜索了这个字段的索引树就不会搜索另一个字段的索引树了,这样会太慢了,因为加载索引也是要耗费磁盘I/O!

key存放age+name,也就是多列索引(联合索引)。先按age排序,再按name排序,age相同,按name进行排序。

image.png 在这个二级索引树上搜索的时候,先搜到age=20有好多个。因为它本身构建这个B+树的时候就是age相等的情况下name已经排好序了,所以这里面不需要再using filesort对name进行排序了。

image.png 不能用到多列索引,因为现在是以name和age创建的索引,所以在B+树上先按age排序再按name排序,如果只拿name作为过滤的话,在这个B+树上就没有办法匹配。所以多列索引使用的时候一定要使用到第一个列

image.png

MyISAM的主键索引树和二级索引树

场景:uid主键,name二级索引

image.png MyISAM下的主键索引树和二级索引树没有区别,唯一的区别就是主键索引树主键是不能重复的,而二级索引树这个普通索引是可以重复的,除此之外,存储方式一模一样。

数据和索引没在一块放叫做非聚集索引,索引和数据都在主键索引树上放的叫聚集索引。

MyISAM就不涉及回表操作了!