插入缓冲 insert buffer、两次写 double write
自适应哈希索引 、异步IO、刷新邻接页
首先对于聚集索引一般是顺序的,插入聚集索引不需要磁盘的随机读取,速度是非常快的,但是表中还存在非聚集索引也就是辅助索引,对于这类索引不一定是自增或者有序的,插入不再是顺序的了,就需要离散的访问非聚集索引页,这样导致了插入性能下降;
也就是说插入缓冲是给 1. 非聚集索引 并且 2. 非唯一索引 设计的;
为什么需要插入缓冲?
首先对于聚集索引一般是顺序的,插入聚集索引不需要磁盘的随机读取,速度是非常快的,但是表中还存在非聚集索引也就是辅助索引,对于这类索引不一定是自增或者有序的,插入不再是顺序的了,就需要离散的访问非聚集索引页,这样导致了插入性能下降;
也就是说插入缓冲是给 1. 非聚集索引 并且 2. 非唯一索引 设计的;
为什么不能是唯一索引?
因为插入缓冲的设计是避免磁盘随机读,如果是唯一索引在插入到插入缓冲前还要进行一次随机读来判断该插入的记录是否唯一,就样失去了插入缓冲的意义了。
非聚集索引的插入流程是?
非聚集索引的插入操作不是每一次直接插入到索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,若在,直接插入;
否则呢,则是放入到insert buffer中,然后再以一定的频率和情况进行insert buffer和辅助索引叶子节点的merge(合并)操作,这时能将多个插入合并到一个操作当中(因为都在一个索引页中),这样就大大提高了对于非聚集索引的插入性能。
insert buffer中的记录什么时候合并到真正的辅助索引中呢?
辅助索引页被读取到缓冲池时;
insert buffer bitMap页追踪到该辅助索引页没有可用空间时;
Master Thread
第一种情况 辅助索引被读取到缓冲池时,此时可以把多个对此索引页的操作记录合并到该页;多次的操作记录通过一次就合并到了原有的辅助页,因此性能会大幅度提升;
第二种情况,insert buffer bitMap页用来追踪每个辅助索引页的可用空间,当辅助页索引空间小于1/32页时,会强制进行一个合并操作,也就是强制读取辅助索引页然后进行合并
第三种情况 innodb 后台线程 Master Thread每隔一段时间会进行一次合并insert buffer的操作,不同之处在于每次进行合并操作的页的数量不同;
记住insert buffer只针对两个必要条件:
非聚集索引
非唯一索引
2. 两次写 double write
为什么需要两次写?
当脏页列表的数据刷新到磁盘例如 正在写入一个14k的页数据到磁盘,此时发生宕机,只写入成功了8k,那么磁盘的页已经不是原生的页数据了,不完整了,如果通过重做日志的方式也无法恢复了,这样的局面我们是无法接受的;
double write的架构是什么样的?
两次写的流程是?
double write包含两部分:
内存中double buffer 和 磁盘上的共享表空间 大小都是2M
从脏页列表缓冲的数据复制到double buffer中,然后分为两次,每次1M的大小刷新到磁盘共享表空间中,共享表空间页时连续的,写入过程顺序写入性能很好,全部写到共享表空间之后马上调用fsync函数将double buffer中的数据离散方式写入到对应的数据页;
3. 自适应哈希索引
哈希的查找复杂度为O(1),一般仅需要一次查询就能定位数,速度非常快,可以进一步提升innodb的性能;
innodb存储引擎会自动根据访问的频率和模式来自动的为某些热点页建立哈希索引;(是给页建立索引不是为某行数据,数据所在的页)
自适应hash索引的创建要求?
自适应hash索引局限是什么?
4. 异步IO
5. 刷新邻接页
当刷新一个脏页时,innodb存储引擎会检测该页所在的区的所有页,如果是脏页,那么一起进行刷新。利用AIO可以将多个IO合并成一个IO操作,该机制在系统机械磁盘上有着显著优势。
答案是不一定的,刷新邻接页带来一个问题就是会不会把不怎么脏的页进行了写入,而该页之后又会很快变成了脏页呢,当然对于机械磁盘性能是肯定提升的减少了IO的次数,但是对于IOPS本身就很高的固态硬盘效果就不明显了,所以innodb存储引擎从1.2.x版本开始提供了innodb_flush_neighbors用来控制是否启用该特性。