InnoDB内存结构和相关主题

InnnDB的内存结构有四种
在这里插入图片描述
1、Buffer Pool
Buffer Pool是主内存中的一个区域,InnoDB在该区域中访问**表和索引数据,**这会加速数据库的访问,因为是内存,丝毫没有I/O压力。

为了提高大容量读取操作的效率,缓冲池分为多个页面,这些页面可能包含多行,页即是mysql的存储单位-数据页,为了提高缓存管理的效率,缓冲池被实现为页面的链接列表,即java中的LinkedList,使用LRU算法的变体将很少使用的数据从缓存中老化掉,这里说的并不全是LRU算法,是一种变体-因为InnoDB不仅仅是简单地把数据页缓存到Buffer Pool,涉及很多的优化策略。知道如何利用缓冲池将经常访问的数据保留在内存中是MySQL优化的重要方面,这里划重点,Buffer Pool也是属于Mysql 调优的一部分。

上面说的LRU算法变体一种解释-当需要空间以将新页面添加到缓冲池时,将驱逐最近使用最少的页面,并将新页面添加到列表的中间,此中点插入策略将列表视为两个子列表,最前面是最近访问过的新(“年轻”)页面的子列表,在末尾,是最近访问过的旧页面的子列表,详细看图

在这里插入图片描述
可以看出3/8的缓冲池专用于旧的子列表,列表的中点是新子列表的尾部与旧子列表的头相交的边界,当InnoDB将页面读入缓冲池时,它最初将其插入中点(旧子列表的头部),访问旧子列表中的页面会使其“年轻”,并将其移至新子列表的开头,最终,未使用的页面到达旧子列表的尾部并被逐出。

针对mysqldump操作或不带WHERE子句的SELECT语句执行的表扫描可以将大量数据带入缓冲池,并驱逐相当数量的旧数据,即使不再使用新数据也是如此,所以不推荐select * 查询可以这样说,你前面很多有用的数据页已经缓存在Buffer Pool了,但是你执行了select *,就可能会把有用的数据页驱逐出去了,进来的都是一些不常用的数据,另外InnoDB预读后台线程加载且仅访问一次的页面将移至新列表的开头,可以通过InnoDB Standard Monitor工具来监控Buffer Pool的详细信息

监控Buffer Pool很简单,使用SHOW ENGINE INNODB STATUS,查看
BUFFER POOL AND MEMORY部分,如图
在这里插入图片描述

上面的这些 InnoDB Buffer Pool 指标有兴趣的小伙伴可以私聊关注我,我一 一道尽,知道有这么一回事就好了,因为不是DBA。关于Buffer Pool只要它是缓存数据页就够了。

2、Change Buffer
首先清楚一点,Change Buffer也是在Buffer Pool里面的,下面是官网对它的解释:用于在二级索引页不在缓冲池中时将更改缓存到二级索引页。
在这里插入图片描述

与聚簇索引不同,二级索引通常是不唯一的,并且二级索引的插入以相对随机的顺序发生,稍后将缓存的更改合并时,通过其他操作将受影响的页读入缓冲池,可以避免从磁盘将辅助索引页读入缓冲池所需的大量随机访问I / O。说到这里,Change Buffer在你插入数据时,先把对这条记录对二级索引所在的树的变化缓存着,后面再合并,注意是二级索引,也就是非主键索引,innoDB为什么这样涉及,应该是考虑到主键索引和非主键索引的一般区别把,主键索引是有序的,非主键索引是无序,如果没来一条DML操作都进行磁盘I/O,成本太高了,等到适当的时候再进行合并,就可以成批写入磁盘了。

在磁盘上,更改缓冲区是系统表空间的一部分,当数据库服务器关闭时,索引更改将存储在其中,这就可以防止意外发生了不丢失数据。

由于Change Buffer功能可以减少磁盘读写操作,因此它对于受I / O限制的工作负载(例如,具有大量DML操作的应用程序,例如批量插入)最有价值。但是,更改缓冲区占用了缓冲池的一部分,从而减少了可用于缓存数据页的内存。如果工作集几乎适合缓冲池,或者您的表具有相对较少的二级索引,则禁用更改缓冲可能很有用。

可以使用innodb_change_buffering配置参数来控制InnoDB执行更改缓冲的程度。建议:可以为插入,删除操作(最初将索引记录标记为删除)和清除操作(物理删除索引记录)启用或禁用缓冲。更新操作是插入和删除的组合。默认的innodb_change_buffering值为all。

Mysql5.7的innodb_change_buffering 可以为如下值
在这里插入图片描述可以通过my.cnf或my.ini配置文件或使用SET GLOBAL 命令动态设置该参数,需要足够的特权来设置全局系统变量。

监控Change Buffer也可以通过输入SHOW ENGINE INNODB STATUS\G命令,并查看下面部分
SHOW ENGINE INNODB STATUS\G

3、Log Buffer
Log Buffer是用于保存要写入磁盘上日志文件的数据的存储区。Log Buffer大小由innodb_log_buffer_size变量定义。默认大小为16MB,Log Buffer的内容定期刷新到磁盘,较大的日志缓冲区使大型事务可以运行,而无需在事务提交之前将redo log数据写入磁盘,因此,如果您有更新,插入或删除许多行的事务,则增加日志缓冲区的大小可以节省磁盘I / O

innodb_flush_log_at_trx_commit变量控制如何将日志缓冲区的内容写入并刷新到磁盘。innodb_flush_log_at_timeout变量控制日志刷新频率。

这Log Buffer其实就是在优化InnoDB redo log,连写盘都不用了,直接缓存,,你说mysql就是这样将缓存发挥到极致以达到最大的数据库性能

4、Adaptive Hash Index(自适应哈希)

自适应哈希索引功能使InnoDB在具有适当的工作负载组合和足够的缓冲池内存的系统上,可以更像内存数据库,而不会牺牲事务功能或可靠性.自适应哈希索引功能由innodb_adaptive_hash_index变量启用,或在服务器启动时由–skip-innodb-adaptive-hash-index关闭

根据观察到的搜索模式,使用索引关键字的前缀构建哈希索引。
该前缀可以是任何长度,并且可能是哈希树索引中仅B树中的某些值出现。哈希索引是根据对经常访问的索引页面的需求而建立的

如果表几乎完全适合主内存,则散列索引可以通过启用直接查找任何元素的方式来加速查询,从而将索引值转换为某种指针。
InnoDB具有一种监视索引搜索的机制。如果InnoDB注意到查询可以从构建哈希索引中受益,它会自动这样做

在某些工作负载下,哈希索引查找的速度大大超过了监视索引查找和维护哈希索引结构的额外工作。
在繁重的工作负载(例如多个并发连接)下,访问自适应哈希索引有时可能会成为争用的源。使用LIKE运算符和%通配符的查询也往往不会受益。对于无法从自适应哈希索引功能中受益的工作负载,将其关闭可减少不必要的性能开销。由于很难预先预测自适应哈希索引功能是否适合特定的系统和工作负载,因此请考虑启用和禁用该功能的基准测试。与早期版本相比,MySQL 5.6中的体系结构更改使它更适合禁用自适应哈希索引功能。

在MySQL 5.7中,自适应哈希索引功能已分区。每个索引都绑定到特定分区,并且每个分区均受单独的锁存器保护。分区innodb_adaptive_hash_index_parts变量控制。在较早的版本中,自适应哈希索引功能受单个闩锁的保护,这可能成为繁重工作负载下的争用点。默认情况下,innodb_adaptive_hash_index_parts变量设置为8。最大设置为512

您可以在SHOW ENGINE INNODB STATUS输出的SEMAPHORES部分中监视自适应哈希索引的使用和争用。如果有很多线程在btr0sea.c中创建的RW锁上等待,请考虑增加自适应哈希索引分区的数量或禁用自适应哈希索引功能

关于这部分,只要知道InnoDB是支持哈希索引就行了,太深的东西需要通过实验和源码才能了解

猜你喜欢

转载自blog.csdn.net/weixin_42002747/article/details/106895416