而不是用严厉LRU算法,InnoDB
使用一种技术来尽量减少输入的数据量缓冲池再也没有进入过。目标是确保经常访问(”热")页仍然保留在缓冲池中,即使预读而且全表扫描引入新的块,这些块之后可能会被访问,也可能不会被访问。
新读取的块被插入到LRU列表的中间。所有新读取的页面都插入到默认位置3/8
从LRU列表的尾部。当第一次在缓冲池中访问页面时,页面被移动到列表的前面(最近使用的一端)。因此,从未被访问的页面永远不会出现在LRU列表的前面部分,并且”年龄了"比严格的LRU方法更快。这种安排将LRU列表划分为两个部分,其中考虑插入点下游的页面”老"并且是LRU驱逐的理想受害者。
的内部工作原理的解释InnoDB
buffer pool和LRU算法的细节,请参见第15.5.1节“缓冲池”.
您可以控制LRU列表中的插入点,并选择是否插入InnoDB
对表或索引扫描带入缓冲池的块应用相同的优化。配置参数innodb_old_blocks_pct
控制百分比”老"块在LRU列表。的默认值innodb_old_blocks_pct
是37
,对应原固定比例3/8。取值范围为5
(缓冲池中的新页面老化很快)到95
(只有5%的缓冲池被预留给热页,使得算法接近我们熟悉的LRU策略)。
防止缓冲池被预读破坏的优化可以避免由于表或索引扫描而产生的类似问题。在这些扫描中,一个数据页通常被快速连续地访问几次,并且再也不会被接触。配置参数innodb_old_blocks_time
指定第一次访问页面后的时间窗口(单位为毫秒),在此期间,可以在不移动到LRU列表的前面(最近使用的一端)的情况下访问页面。的默认值innodb_old_blocks_time
是1000
.增加这个值会使越来越多的块更快地从缓冲池中老化。
这两个innodb_old_blocks_pct
而且innodb_old_blocks_time
可以在MySQL选项文件(my.cnf
或my.ini
)或在运行时使用集全球
声明。在运行时更改值需要足够的权限来设置全局系统变量。看到第5.1.9.1节,“系统变量特权”.
为了帮助您衡量设置这些参数的效果,请使用显示引擎innodb状态
命令用于查询缓冲池统计信息。详细信息请参见使用InnoDB Standard Monitor监控缓冲池.
因为这些参数的效果会根据硬件配置、数据和工作负载的细节而有很大差异,所以在任何性能关键型环境或生产环境中更改这些设置之前,始终要进行基准测试以验证其有效性。
在混合工作负载中,大多数活动都是OLTP类型,具有周期性的批报告查询,这会导致大型扫描,将值设置为innodb_old_blocks_time
在批处理运行期间,可以帮助在缓冲池中保持正常工作负载的工作集。
当扫描无法完全放入缓冲池的大表时,设置innodb_old_blocks_pct
到较小的值可以防止只读取一次的数据占用缓冲池的很大一部分。例如,设置innodb_old_blocks_pct = 5
将只读取一次的数据限制在缓冲池的5%。
当扫描适合内存的小表时,在缓冲池中移动页面的开销更少,因此可以离开innodb_old_blocks_pct
在其默认值,甚至更高,如innodb_old_blocks_pct = 50
.
的影响innodb_old_blocks_time
参数比innodb_old_blocks_pct
参数的值相对较小,并且随着工作负载的变化而变化。为了达到最优值,如果通过调整性能得到改善,可以进行自己的基准测试innodb_old_blocks_pct
是不够的。