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

  • 溢出列
    如果一个列太长,并不会傻乎乎的存储所有数据在行记录中,而是使用溢出列 , COMPACTREDUNDANT只会存储该列的前768字节然后存储指向其他页的地址,剩下的数据存在其他页中 。
  • DYNAMIC和COMPRESSED
    COMPACT类似,但是二者不会存储过长列的前768字节,而是把真实数据都存储到溢出中 , 记录只存储溢出页的地址 。COMPRESSED 还会使用压缩算法对页面进行压缩
  • 2.InnoDB页结构页是InnoDB管理存储空间的基本单位,其默认大小为16k,InnoDB设计了很多不同的页结构:存放Change Buffer的页 , 存储undo log 日志的页等等 。对于表中数据,也存在在页中
    究极无敌细节版 Mysql索引

    文章插图
    最开始的时候UserRecords并不存在,随着数据的插入,会从FreeSpace中申请一个记录大小的空间,将其划分到UserRecords部分,当FreeSpace用完只会继续插入就需要申请新的页 。
    2.1行结构中记录头信息的作用
    • deleted_flag:标记是否被删除,1表示被删除,被删除的列表通过next_record串联起来,并且会记录被删除记录的空火箭,这部分空间可以重复使用
    • min_rec_flag: B+树每层非叶子节点,最小的目录项记录会被添加此标记
    • n_owned:
    • heap_no:UserRecords中存储的用户记录是紧凑如同一样排布的,heap_no是堆中记录的编号 , 从2开始(0和1 被infimum+supremum占用,infimum虚拟的最小记录,supremum虚拟最大记录)
    • next_record:表示当前记录的真实数据,到下一条记录的距离
      究极无敌细节版 Mysql索引

      文章插图
      next_record左边是变长字段列表null值列表(二者都是逆序存放信息,也就是说距离next_record最近的是第一个字段是否为null,第一个变长字段的长度)右边是记录的真实数据(顺序存放),且可以使记录中靠前字段和对应的字段信息在内存中更近,提高高速缓存的命中率 。这里我们可以看到被删除的记录没用立即被清除,只是不会被next_record串联起来
      记录按照主键从小到大形成单向链表
    2.2页目录上面我们知道了记录在页中按照主键从小到大的顺序串联成单向链表,那么怎么在一个页中根据主键找到目标记录昵——通过页目录进行二分查找 。
    1. 页目录生成过程
      1. 将infimum,supermum以及所有未被删除的记录 , 分成多个组
      2. 每一个组中最大的记录的n_owned存储组中记录条数
      3. 将每一个组中最后的记录在页面中的地址偏移量,存储到页面尾部——Page Directory中,这些地址偏移量称为

      究极无敌细节版 Mysql索引

      文章插图
    2. 根据查询页面记录的过程
      通过二分法找到目标记录中的槽,然后遍历槽所在组的所有记录
    3.InnoDB索引方案3.1为页建立目录项InnoDB使用也作为管理和存储空间的基本单位 , 最多只能保证16k的连续存储 。
    究极无敌细节版 Mysql索引

    文章插图
    目录项记录的只是主键值和页号两个列 , 最下方是我们刚刚讲到的innoDB存储用户记录的页 。如果页面数据量很大,可以继续为目录项建立目录项
    究极无敌细节版 Mysql索引

    文章插图
    3.2 根据目录项定位数据行的过程例如查找主键为10记录
    1. 根据目录项中的内容,确定目标记录所在的页
      如上图页33 存在记录(1,30),(320 32),可以判断主键位于1~320范围的记录在页30,大于320的记录在页32
    2. 找到页30后还要继续在页30中,通过目录项记录的页确定目标记录真正所在的页
    3. 在真正存储用户记录的页(页28)中通过槽定位到组,然后遍历槽所在组的所有记录
    三丶聚集索引和非聚集索引InnoDB存储引擎是索引组织表——表中的数据按照主键顺序存放 。非聚集索引也称做辅助索引 , 无论是聚集还是非聚集,其原理都是一颗B+树,叶子节点都存储数据 , 不同的是聚集索引叶子节点存储的是一整行的数据 , 非聚集索引叶子节点存储的是聚集索引值(主键值) 。

    推荐阅读