insert buffer 是InnoDB存储引擎所独有的功能。通过insert buffer,InnoDB存储引擎可以大幅度提高数据库中非唯一辅助索引的插入性能。

数据库对于自增主键值的插入是顺序的,因此插入能有较高的性能。但是实际生产环境中,用户表中主键仅有并且只能有1个,然而表中可能存在多个辅助索引。

为了阐述非聚集索引写性能问题,我们先来看一个例子:

mysql>create table t (
           id int auto_increment,
           name varchar(30),
           primary key (id));

我们创建了一个表,表的主键是id,id列式自增长的,即当执行插入操作时,id列会自动增长,页中行记录按id顺序存放,不需要随机读取其它页的数据。因此,在这样的情况下(即聚集索引),插入操作效率很高。

对于上一张表t,业务上还需要按非唯一的name字段查找,则表定义改为:

mysql>create table t (
           id int auto_increment,
           name varchar(30),
           primary key (id),
           key (name));

这时,除了主键聚合索引外,还产生了一个name列的辅助索引,对于该非聚集索引来说,叶子节点的插入不再有序,这时就需要离散访问非聚集索引页,插入性能变低。

插入缓冲原理

为了解决这个问题,InnoDB设计出了插入缓冲技术,对于非聚集类索引的插入和更新操作,不是每一次都直接插入到索引页中,而是先判断插入的非聚集索引叶子是否在缓冲池中,若在,则直接插入;若不在,则先将插入的记录放到insert buffer中,然后根据一些算法将insert buffer 缓存的记录通过后台线程慢慢的合并(merge)回辅助索引页中。这样做的好处是:(1)减少磁盘的离散读取;(2)将多次插入合并为一次操作。

例如name字段的插入顺序为:

('Maria',10), ('David',7), ('Tim', 11), ('Jim', 7), ('Monty', 10), ('Herry', 7), ('Heikki', 7)

后面的数字表示原先插入的辅助索引的page_no,可以看到页的访问是完全无序的,然而当插入到insert buffer中时,上述记录可能在一个页中,因此减少了离散读取。在insert buffer中,记录根据应插入辅助索引的叶子节点page_no进行排序,故上述记录在insert buffer中的状态应为:

('David',7), ('Jim', 7), ('Herry', 7), ('Heikki', 7) , ('Maria',10), ('Monty', 10), ('Tim', 11)

当要进行合并时,页page_no为7的记录有4条,可以一次性将这4条记录插入到辅助索引中,从而提高数据库的整体性能。

insert buffer的使用需要满足以下两个条件:

(1)索引是辅助索引(secondary index)

(2)索引是非唯一的

若是唯一索引,那么在插入时需要判断插入的记录是否是唯一,这需要读取辅助索引页,而insert buffer 的设计就是避免读取insert buffer,这会导致失去insert buffer 的设计意义。

插入缓冲的内部实现

insert buffer的数据结构是一棵B+树。在MySQL4.1之前的版本中每张表都有一棵insert buffer B+树。而在现在的版本中,全局只有一棵insert buffer B+树,负责对所有的表的辅助索引进行 insert buffer。这棵B+树存放在共享表空间中,默认也就是ibdata1中。因此,试图通过独立表空间ibd文件恢复表中数据时,往往会导致check table 失败。这是因为表的辅助索引中的数据可能还在insert buffer中,也就是共享表空间中。所以通过idb文件进行恢复后,还需要进行repair table 操作来重建表上所有的辅助索引。

insert buffer是一棵B+树,因此其也由叶子节点和非叶子节点组成。非叶子节点存放的是查询的search key(键值)。其构造包括三个字段:space | marker | offset。

search key一共占9字节,其中space占4字节,marker占1字节、offset占4字节。space表示待插入记录所在的表空间id,在InnoDB存储引擎中,每个表有一个唯一的space id,可以通过space id查询得知是哪张表。marker是用来兼容老版本的insert buffer。offset表示页所在的偏移量。

当一个辅助索引需要插入到页(space, offset)时,如果这个页不在缓冲池中,那么InnoDB存储引擎首先根据上述规则构造一个search key,接下来查询insert buffer这棵B+树,然后再将这条记录插入到insert buffer B+树的叶子节点中。

对于插入到insert buffer B+树叶子节点的记录,需要根据如下规则进行构造:

space | marker | offset | metadata | secondary index record

启用insert buffer索引后,辅助索引页(space、page_no)中的记录可能被插入到insert buffer B+树中,所以为了保证每次merge insert buffer页必须成功,还需要有一个特殊的页来标记每个辅助索引页(space、page_no)的可用空间。这个页的类型为insert buffer bitmap。

概括的说,merge insert buffer的操作可能发生在以下几种情况:

(1)辅助索引页被读取到缓冲池时;

(2)insert buffer bitmap页追踪到该辅助索引页已无可用空间时;

(3)master thread。

插入缓冲带来的问题

插入缓冲主要带来如下两个坏处:

(1)可能导致数据库宕机后实例恢复时间变长。如果应用程序执行大量的插入和更新操作,且涉及非唯一的聚集索引,一旦出现宕机,这时就有大量内存中的插入缓冲区数据没有合并至索引页中,导致实例恢复时间会很长。

(2)在写密集的情况下,插入缓冲会占用过多的缓冲池内存(innodb_buffer_pool),默认情况下最大可以占用1/2,这在实际应用中会带来一定的问题。

插入缓冲的升级:change buffer

InnoDB从1.0.x版本开始引入了change buffer,可以将其视为insert buffer的升级。从这个版本开始,InnoDB存储引擎可以对DML操作——insert、delete、update都进行缓冲,它们分别是:insert buffer、delete buffer、purge buffer。

和insert buffer一样,change buffer适用的对象依然是非唯一的辅助索引。

对一条记录进行update操作可以分为两个过程:

(1)将记录标记为删除;

(2)真正将记录删除。

因此delete buffer对应update操作的第一个过程,即将记录标记为删除。purge buffer对应update操作的第二个过程,即将记录真正的删除。同时InnoDB存储引擎提供了参数innodb_change_buffering,用来开启各种buffer选项。该参数的可选值为:inserts、deletes、purges、changes、all、none。inserts、deletes、purges就是前面讨论过的三种情况。changes表示启用inserts和deletes,all表示启用所有,none表示都不启用。

InnoDB关键特性之insert buffer的更多相关文章

  1. innodb 关键特性(insert buffer)

    一.insert buffer 性能改善 insert buffer和数据页一样,也是物理页的一个组成部分. 在innodb存储引擎中,主键是行唯一的标识符.通常应用程序中行记录的插入顺序是按照主键递 ...

  2. InnoDB关键特性之change buffer

    一.关于IOT:索引组织表 表在存储的时候按照主键排序进行存储,同时在主键上建立一棵树,这样就形成了一个索引组织表,一个表的存储方式以索引的方式来组织存储的. 所以,MySQL表一定要加上主键,通过主 ...

  3. 【mysql】Innodb三大特性之insert buffer

    一.什么是insert buffer insert buffer是一种特殊的数据结构(B+ tree)并不是缓存的一部分,而是物理页,当受影响的索引页不在buffer pool时缓存 secondar ...

  4. InnoDB关键特性学习笔记

    插入缓存 Insert Buffer Insert Buffer是InnoDB存储引擎关键特性中最令人激动与兴奋的一个功能.不过这个名字可能会让人认为插入缓冲是缓冲池中的一个组成部分.其实不然,Inn ...

  5. innodb关键特性之double write

    # 脏页刷盘的风险 两次写的原理机制 1.解决问题 2.使用场景 3.doublewrite的工作流程 4.崩溃恢复 # doublewrite的副作用 1.监控doublewrite负载 2.关闭d ...

  6. my36_InnoDB关键特性之change buffer

    一.关于IOT:索引组织表 表在存储的时候按照主键排序进行存储,同时在主键上建立一棵树,这样就形成了一个索引组织表,一个表的存储方式以索引的方式来组织存储的. 所以,MySQL表一定要加上主键,通过主 ...

  7. InnoDB关键特性之刷新邻接页-异步IO

    Flush neighbor page 1.工作原理 2.参数控制 AIO 1.开启异步IO 一.刷新邻接页功能 1.工作原理 当刷新一个脏页时,innodb存储引擎会检测该页所在区(extent)的 ...

  8. InnoDB关键特性之自适应hash索引

    一.索引的资源消耗分析 1.索引三大特点 1.小:只在一个到多个列建立索引 2.有序:可以快速定位终点 3.有棵树:可以定位起点,树高一般小于等于3 2.索引的资源消耗点 1.树的高度,顺序访问索引的 ...

  9. innodb 关键特性(两次写与自适应哈希索引)

    两次写: 场景: 当发生数据库宕机时,可能innodb存储引擎正在写入某个页到表中,而这个页只写了一部分,这种情况被称为部分写失效,如果发生,可以通过重做日志进行恢复,重做日志中记录的是对页的物理操作 ...

随机推荐

  1. 【BZOJ 1009】 [HNOI2008]GT考试

    Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学A1A2...Am(0< ...

  2. 玩转Log4Net

    玩转Log4Net 下载Log4Net 下载地址:http://logging.apache.org/log4net/download_log4net.cgi 把下载的  log4net-1.2.11 ...

  3. 集成“支付宝” -b

    大致步骤 1.与支付宝签约获取相关参数 合作者身份 ID 与安全校验码 key2.下载需要导入的文件,做相应设置3.在自己的项目中集成支付的方法代码 详细步骤 1.获取合作者身份 ID 与安全校验码 ...

  4. hdu 4717 The Moving Points(第一个三分题)

    http://acm.hdu.edu.cn/showproblem.php?pid=4717 [题意]: 给N个点,给出N个点的方向和移动速度,求每个时刻N个点中任意两点的最大值中的最小值,以及取最小 ...

  5. 内存泄露 memory leak 的原因

    #include <iostream> using namespace std; void foo() { MyClass *x; x = new MyClass(); //指向的丢失了 ...

  6. js的面向对象的程序设计之理解继承

    来自<javascript高级程序设计 第三版:作者Nicholas C. Zakas>的学习笔记(六) 先来解析下标题——对象和继承~ 一.对象篇 ECMA-262把对象的定义为:&qu ...

  7. jquery判断对象是否获得焦点

    var isFocus=$("#tRow").is(":focus"); if(true==isFocus){ alert("focus") ...

  8. 汇编Ring 3下实现 HOOK API

    [文章标题]汇编ring3下实现HOOK API [文章作者]nohacks(非安全,hacker0058) [作者主页]hacker0058.ys168.com [文章出处]看雪论坛(bbs.ped ...

  9. AxureRP制作Tab标签

    1.添加动态Panel 2.双击进入编辑动态Panel 3.点击一个面板状态,编辑全部状态 4.选择虚线框,画出两个矩形图,一大一小:

  10. uva 10730

    题意:如果数列中没有三个元素的子序列构成等差数列输出yes 不然no 标记每个数出现的位置  然后从0开始寻找三个元素的等差数列  如果这三个元素的位置满足条件则原数列中存在等差数列 #include ...