MYSQL-InnoDB索引

索引

索引在Mysql中是很有用的,通过索引能够很快速的找到我们所要查询的数据.这里讲一下InnoDB存储引擎中的索引实现.

B+索引

在InnoDB引擎中,索引是通过B+树来实现的.并且是聚集索引.B+树不理解的可以去搜一下,网上教程挺多的.B+树索引在数据库中有一个特性就是高扇出性,在数据库中,树的高度一般都是2-4层.这也就是说一般查找某一个键值的记录只需要进行2-4次IO就可以.

在InnoDB引擎中中B+树索引可以分为聚集索引和辅助索引,他们两个不同的地方在与聚集索引的叶子节点中存放的是行记录,辅助索引中存放的是主键值.在B+树中,非叶子节点也就是索引节点,非叶子节点是真正存储数据的节点.两种索引不同的地方在于叶子节点存放的数据是不同的.

聚集索引

InnoDB引擎表是索引组织表,就是表中数据按照主键顺序存放.而聚集索引就是按照每张表的主键id构造一颗B+树,同时叶子节点中存放的就是整张表的行记录数据,就是聚集索引的叶子节点为数据页.上一篇博文说过在InnoDB中的数据都是按照页来存储的.这里B+树中的每个节点都对应一个页.大小为16KB.每个数据页都是由一个双向链表来连接的.

辅助索引

辅助索引,叶子节点并不包含行记录的全部数据.叶节点除了包含键值以外,每个叶子节点中的索引行中还包含了一个书签.该书签用来告诉InnoDB在哪里可以找到与索引相对应的行数据.这个书签其实就是对应的行数据的聚集索引键.

因此在InnoDB中如果通过辅助索引来查找数据的,IO次数会比按照主键查询多一倍.

B+树索引的分裂

传统的B+树索引的分裂是直接从中间开始分裂的.这种情况可能会导致一个问题就是分裂之后的数据页大部分空间都被浪费了.比如说一页中存储4条数据.插入1,2,3,4.是一页.这时候再插入5.会将1,2为一页,但是这一个节点中不会在存储其他的任何东西.会导致空间浪费.

针对这一点,INnoDB对于B+树索引的分裂做了一点小优化.对此InnoDB做了简单调整.
在InnoDB引擎中的PageHeader中有一下几个部分用来保存插入的顺序信息:

  • PAGE_LAST_INSERT
  • PAGE_DIRECTION
  • PAGE_N_DIRECTION

通过这些信息,InnoDB引擎可以决定是向左还是向右进行分裂.同时决定分裂点记录为哪一个.如果插入是随机的,则取页的中间记录作为分裂点的记录.这里没有优化.而如果上次的插入是递增或递减的,那么会做出一些优化.
比如向某一方向插入的记录数量为5,并且目前已经定位到的记录(InnoDB引擎插入时,首先需要进行定位,定位到的记录为带插入记录的前一条记录)之后还有三条记录,则分裂点的记录为定位到的记录后的第三条记录.

Multi-Range Read优化

MySQL5.6版本开始支持Multi-Range Read优化.简称(MRR)优化,这个优化主要目的就是为了减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问.因为顺序访问磁盘效率会高,这里MRR会根据辅助索引查询的结果对主键进行排序,按照主键排序的顺序进行书签查找. 其次就是能够减少缓冲池中页被替换的次数. 批量处理对键值的查询操作.

MRR工作方式如下:

  • 将查询到的辅助索引键放入一个缓存中,这是缓存的数据根据辅助索引键排序
  • 借着按照ROWID来进行排序
  • 根据RowID的排序顺序来访问实际的数据文件.