究极无敌细节版 Mysql索引( 四 )


究极无敌细节版 Mysql索引

文章插图

究极无敌细节版 Mysql索引

文章插图
如果数据表定义了主键,那么这个主键索引就是聚集索引,如果没有定义主键,mysql会选择该表的第一个非空唯一的索引构建聚集索引,如果都没有那么mysql会生成一个隐藏的列(6字节的列,并且插入自增)
自增主键会把数据自动向后插入,避免了插入过程中聚集索引节点分裂的问题 。节点分裂会带来大范围的数据物理移动 , 带来磁盘IO的性能损耗,并且我们一般建议尽量不要改动主键,主键的更改也会带来page分裂 , 产生碎片 。
四丶回表查询
究极无敌细节版 Mysql索引

文章插图

究极无敌细节版 Mysql索引

文章插图
如上图,假如我们有一张表存在三个字段id,age,name我们在id上建立了主键索引,这时候id主键索引也是聚集索引,在age上建立了普通索引,这时候age索引就是非聚集索引 。如果我们执行select * from table where age=1这时候先走age索引(如果数据量较大,数据量少直接全表扫描了)那么会找到对应的主键id , 继续到主键id索引中找到目标数据 , 这个操作叫做回表 。
这就是为什么根据主键查找快于根据其他索引列查找 , 因为如果其他索引列没有包含我们select语句中需要的列(如果是select id from table where age<10,那么age索引是可以覆盖到需要的数据的(叶子节点存储了id),那么也不会回表),那么会走主键索引拿到需要的数据,多了一步回表操作 。
这里我们也可以看到为什么建议使用select * ,这意味着查找所有列,如果配合上普通索引,那么大概率这个普通索引不会覆盖到索引列,导致需要回表查询 。并且select*这种"我全都要"大概率会查询到我们不需要的列 , 造成不必要的网络资源消耗,增加不必要的io,增加不必要的内存消耗 。
五丶联合索引
究极无敌细节版 Mysql索引

文章插图

究极无敌细节版 Mysql索引

文章插图
联合索引是指对表上的多个列建立索引,如上图表存在四个字段id,address,name,age,我们在name和age上建立索引,上图我们粗略的展示了联合索引的B+树结构 。我们可以观察到在叶子节点中name是有序的,但是age无序,联合索引是按照索引定义的顺序排序的,这就导致select xxx from table where name='b'是可以根据上面定义的联合索引查找数据的,但是``select xxx from table where age=12是无法走上面定义的联合索引的 。这就是常说的最左前缀匹配原则`的原理 。