先来说一下我们之前的一个误区:
我之前以为取数据计算机是这个样的一个流程:
机械硬盘-->内存-->cpu缓存(L1L2L3)-->cpu处理
这样理解并没有什么大的毛病,但是我们忽略来中间还有一层那就是缓冲层(这里也就是change buffer、buffer pool的位置),这一层在哪里呢?这就是在机械硬盘到内存的中间还有一层:机械硬盘-->缓冲层-->内存。这个问题也就是我一直没有理解buffer poolchange buffer的原因所在。
计算机在机械硬盘拿数据其实也就是一页一页的拿取的(一页的数据是4kb),innodb一页的数据是16kb也就是说我们查询出来的数据,MySQL就是16kb,16kb的读入的。
在使用索引查询的时候,我们通过索引的B+树找到索引的根节点,叶子节点存的是一页一页的数据,我们先从叶子节点找到所在的查询的一页数据,然后通过二分法来查找一行的数据。然后再通过回表来找到data的数据。
我们有来这个概念之后,我们再来说我们查到来数据之后,我们就是一页一页的将数据先放到缓冲池中(buffer pool中),对于查询来说,缓冲池有一个lru淘汰策略来淘汰缓冲池中的数据,这样就可以减少MySQL的随机读取硬盘的io可以提高查询效率。因为查询如果数据没有在缓冲池中的话,他会在磁盘中读取数据,增加磁盘的io次数。
然后我们再来说说change buffer,这个只是针对更新(update)以及插入(insert)
update:如果数据在change buffer中就直接更新,不在change buffer中就先把它拉到change buffer中再来更新。(我们先把数据记在缓冲中,是不是就可以提高来内存的利用率)
那什么时候需要把数据持久化(merge)到磁盘上呢?
1.读取该条数据的时候
2.后台会有线程定期merge
3.数据库关闭的时候
另:要是唯一索引的话,是不是就没有必要来,因为唯一索引会有一次判断过程,要把数据先读入内存中判断,这样再用change buffer就有点没有必要了,然后说到了唯一索引的判断,我们是不是可以理解为,如果是插入语句的话,唯一索引的每次插入都要做判断必然是会影响效率的,但是普通索引又不一样了,普通索引就可以直接存到change buffer中,然后定期merge就可以了。
那么也就是说,change buffer只能适用于写多读少的时候,对于读多写少的时候,就会有副作用了。(因为每次读都会产生一个merge)
然后再就是我之前思考的一个疑问:change buffer redo log有什么关系呢?
1.redo log只是一个日志(要写盘的)
2.change buffer在更新的时候,只是在缓冲区数据页信息记录这个信息(不用写盘)然后再merge就行
注:redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”