Mysql的存储引擎和索引

能够说数据库必须有索引,没有索引则检索过程变成了顺序查找,O(n)的时间复杂度几乎是不能忍受的。咱们很是容易想象出一个只有单关键字组成的表如何使用B+树进行索引,只要将关键字存储到树的节点便可。当数据库一条记录里包含多个字段时,一棵B+树就只能存储主键,若是检索的是非主键字段,则主键索引失去做用,又变成顺序查找了。这时应该在第二个要检索的列上创建第二套索引。  这个索引由独立的B+树来组织。有两种常见的方法能够解决多个B+树访问同一套表数据的问题,一种叫作聚簇索引(clustered index ),一种叫作非聚簇索引(secondary index)。这两个名字虽然都叫作索引,但这并非一种单独的索引类型,而是一种数据存储方式。对于聚簇索引存储来讲,行数据和主键B+树存储在一块儿,辅助键B+树只存储辅助键和主键,主键和非主键B+树几乎是两种类型的树。对于非聚簇索引存储来讲,主键B+树在叶子节点存储指向真正数据行的指针,而非主键。算法

  InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法便可查找到对应的叶节点,以后得到行数据。若对Name列进行条件搜索,则须要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操做,最终到达叶子节点便可获取整行数据。sql

  MyISM使用的是非聚簇索引,非聚簇索引的两棵B+树看上去没什么不一样,节点的结构彻底一致只是存储的内容不一样而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来讲,这两个键没有任何差异。因为索引树是独立的,经过辅助键检索无需访问主键的索引树。数据库

  为了更形象说明这两种索引的区别,咱们假想一个表以下图存储了4行数据。其中Id做为主索引,Name做为辅助索引。图示清晰的显示了聚簇索引和非聚簇索引的差别。数据结构

  咱们重点关注聚簇索引,看上去聚簇索引的效率明显要低于非聚簇索引,由于每次使用辅助索引检索都要通过两次B+树查找,这不是画蛇添足吗?聚簇索引的优点在哪?性能

  1 因为行数据和叶子节点存储在一块儿,这样主键和行数据是一块儿被载入内存的,找到叶子节点就能够马上将行数据返回了,若是按照主键Id来组织数据,得到数据更快。优化

  2 辅助索引使用主键做为"指针" 而不是使用地址值做为指针的好处是,减小了当出现行移动或者数据页分裂时辅助索引的维护工做,使用主键值看成指针会让辅助索引占用更多的空间,换来的好处是InnoDB在移动行时无须更新辅助索引中的这个"指针"。也就是说行的位置(实现中经过16K的Page来定位,后面会涉及)会随着数据库里数据的修改而发生变化(前面的B+树节点分裂以及Page的分裂),使用聚簇索引就能够保证无论这个主键B+树的节点如何变化,辅助索引树都不受影响。3d

  3 Page结构

  若是说前面的内容偏向于解释原理,那后面就开始涉及具体实现了。指针

  理解InnoDB的实现不得不提Page结构,Page是整个InnoDB存储的最基本构件,也是InnoDB磁盘管理的最小单位,与数据库相关的全部内容都存储在这种Page结构里。Page分为几种类型,常见的页类型有数据页(B-tree Node)Undo页(Undo Log Page)系统页(System Page) 事务数据页(Transaction System Page)等。单个Page的大小是16K(编译宏UNIV_PAGE_SIZE控制),每一个Page使用一个32位的int值来惟一标识,这也正好对应InnoDB最大64TB的存储容量(16Kib * 2^32 = 64Tib)。一个Page的基本结构以下图所示:blog

  每一个Page都有通用的头和尾,可是中部的内容根据Page的类型不一样而发生变化。Page的头部里有咱们关心的一些数据,下图把Page的头部详细信息显示出来:索引

 

  咱们重点关注和数据组织结构相关的字段:Page的头部保存了两个指针,分别指向前一个Page和后一个Page,头部还有Page的类型信息和用来惟一标识Page的编号。根据这两个指针咱们很容易想象出Page连接起来就是一个双向链表的结构。

  再看看Page的主体内容,咱们主要关注行数据和索引的存储,他们都位于Page的User Records部分,User Records占据Page的大部分空间,User Records由一条一条的Record组成,每条记录表明索引树上的一个节点(非叶子节点和叶子节点)。在一个Page内部,单链表的头尾由固定内容的两条记录来表示,字符串形式的"Infimum"表明开头,"Supremum"表明结尾。这两个用来表明开头结尾的Record存储在System Records的段里,这个System Records和User Records是两个平行的段。InnoDB存在4种不一样的Record,它们分别是1主键索引树非叶节点 2主键索引树叶子节点 3辅助键索引树非叶节点 4辅助键索引树叶子节点。这4种节点的Record格式有一些差别,可是它们都存储着Next指针指向下一个Record。后续咱们会详细介绍这4种节点,如今只须要把Record当成一个存储了数据同时含有Next指针的单链表节点便可。

  User Record在Page内以单链表的形式存在,最初数据是按照插入的前后顺序排列的,可是随着新数据的插入和旧数据的删除,数据物理顺序会变得混乱,但他们依然保持着逻辑上的前后顺序。

  把User Record的组织形式和若干Page组合起来,就看到了稍微完整的形式。

  如今看下如何定位一个Record:

  1 经过根节点开始遍历一个索引的B+树,经过各层非叶子节点最终到达一个Page,这个Page里存放的都是叶子节点。

  2 在Page内从"Infimum"节点开始遍历单链表(这种遍历每每会被优化),若是找到该键则成功返回。若是记录到达了"supremum",说明当前Page里没有合适的键,这时要借助Page的Next Page指针,跳转到下一个Page继续从"Infimum"开始逐个查找。

  详细看下不一样类型的Record里到底存储了什么数据,根据B+树节点的不一样,User Record能够被分红四种格式,下图种按照颜色予以区分。

  1 主索引树非叶节点(绿色)

  1 子节点存储的主键里最小的值(Min Cluster Key on Child),这是B+树必须的,做用是在一个Page里定位到具体的记录的位置。

  2 最小的值所在的Page的编号(Child Page Number),做用是定位Record。

  2 主索引树叶子节点(黄色)

  1 主键(Cluster Key Fields),B+树必须的,也是数据行的一部分

  2 除去主键之外的全部列(Non-Key Fields),这是数据行的除去主键的其余全部列的集合。

  这里的1和2两部分加起来就是一个完整的数据行。

  3 辅助索引树非叶节点非(蓝色)

  1 子节点里存储的辅助键值里的最小的值(Min Secondary-Key on Child),这是B+树必须的,做用是在一个Page里定位到具体的记录的位置。

  2 主键值(Cluster Key Fields),非叶子节点为何要存储主键呢?由于辅助索引是能够不惟一的,可是B+树要求键的值必须惟一,因此这里把辅助键的值和主键的值合并起来做为在B+树中的真正键值,保证了惟一性。可是这也致使在辅助索引B+树中非叶节点反而比叶子节点多了4个字节。(即下图中蓝色节点反而比红色多了4字节)

  3 最小的值所在的Page的编号(Child Page Number),做用是定位Record。

  4 辅助索引树叶子节点(红色)

  1 辅助索引键值(Secondary Key Fields),这是B+树必须的。

  2 主键值(Cluster Key Fields),用来在主索引树里再作一次B+树检索来找到整条记录。

  下面是本篇最重要的部分了,结合B+树的结构和前面介绍的4种Record的内容,咱们终于能够画出一幅全景图。因为辅助索引的B+树与主键索引有类似的结构,这里只画出了主键索引树的结构图,只包含了"主键非叶节点"和"主键叶子节点"两种节点,也就是上图的的绿色和黄色的部分。

  把上图还原成下面这个更简洁的树形示意图,这就是B+树的一部分。注意Page和B+树节点之间并无一一对应的关系,Page只是做为一个Record的保存容器,它存在的目的是便于对磁盘空间进行批量管理,上图中的编号为47的Page在树形结构上就被拆分红了两个独立节点。

  至此本篇就算结束了,本篇只是对InnoDB索引相关的数据结构和实现进行了一些梳理总结,并未涉及到Mysql的实战经验。这主要是基于几点缘由:

  1 原理是基石,只有充分了解InnoDB索引的工做方式,咱们才有能力高效的使用好它。

  2 原理性知识特别适合使用图示,我我的很是喜欢这种表达方式。

  3 关于InnoDB优化,在《高性能Mysql》里有更加全面的介绍,对优化Mysql感兴趣的同窗彻底能够本身获取相关知识,我本身的积累还未达到能分享这些内容的地步。

  另:对InnoDB实现有更多兴趣的同窗能够看看Jeremy Cole的博客(参考文献三篇文章的来源),这位老兄曾前后在Mysql,Yahoo,Twitter,Google从事数据库相关工做,他的文章很是棒!

相关文章
相关标签/搜索