BufferPool和Changebuffer是如何加快读写速度的?
BufferPool
在Mysql启动的时候 Mysql会申请连续的空间来存储BufferPool
每个页16kb 当控制块不足以存储信息的时候就会向后申请一个新的页
每个控制块都对应了一个缓存页 控制块占chunk的百分之5左右
LRU链表
Changebuffer
非唯一索引的变更
并不会每次都直接进行磁盘IO 而是会先写入Changebuffer 这样如果需要读操作 就不用再去磁盘中io 减少了一次io 提高读写效率
总结
为了优化Mysql的读写效率 在内存中会有一块叫BufferPool 的空间 这里面会存储很多chunk
每个chunk 会存储许多控制块
每个控制块会对应一块缓存页
而为了维护缓存页的状态 就引入了Free链表
和Flush链表
这两个链表存储的都是缓存页对应的控制块
Free链表
: 用来存储有那些控制块是空闲的 就是没有写入数据 (可用的)
Flush链表
:用来存储BufferPool中哪些缓存页是有数据的
脏页
:缓存页中和磁盘数据不一致的就被称为脏页 会定期刷盘来同步缓存
Changebuffer
:修改数据的时候会先写入BufferPool中的Changebuffer 来提高读写效率
预读
:每次读取磁盘的时候会认为这部分的内容可能会被连续访问 于是就连续读取一部分数据页到缓存中
LRU链表
:分为新生代和老年代 通过维护这两块区域 来实现冷热数据分离 避免全表扫描导致热点数据被覆盖
Mysql中的索引
索引下推
顾名思义 将索引从Server层下推到索引层去进行条件的过滤 避免多次回表
举个例子
比如模糊查询姓张的 age=18
那会先查询出姓张的 id=1/4 得到主键后回表根据1、4 在得到姓张的
再到Server层 对age=18进行过滤
索引下推
:
可以直接将条件下方到索引层
可以直接通过两个条件过滤数据行 然后回表查询
这样下来就减少了一次回表查询
页分裂的原因
假设每个Page页只能存放3条数据 当有一个主键为4的数据想要插入的时候
此时为了满足下一个数据页的主键大于上一个页的主键的约定:必须进行数据的移动 5右移 3插入
数据移动造成开销
聚簇索引
联合索引
自适应哈希索引
可以理解为索引的索引 这是Innodb自己创建的
当缓存中的数据经常被访问的时候 innodb会创建AHI 来提高索引的效率
通过O1 HashKV Key 存储热点数据 Value存储位置
在更新数据的时候BufferPool RedologBuffer 和三大日志会发生什么
当一个Update语句发生时:
1.Innodb会从磁盘中读取中对应的数据页到BufferPool 然后对BufferPool中的数据进行修改
2.同时将旧的数据写入Undolog方便数据进行回滚操作 以及配合MVCC进行多版本并发控制
3.然后将数据写入redologbuffer
为机器宕机后恢复数据做兜底操作
Redolog有自己的刷盘策略
1.延迟写 2.实时写 延时刷 3.实时写实时刷
当redolog刷盘后 此时如果宕机 但是事务还没提交 就可以通过redolog(记录的是物理数据)恢复
同时还会标记Prepare
状态(两阶段提交)
4.同时也会写binlog (记录的是逻辑日志) 并且把redolog
中的状态改为commit
Mysql架构
这也是innodb区别于其他存储引擎特有的支持事务的原因对吗 持久性 原子性