17.8.3.3 缓冲池扫描抵抗
而不是使用严格的LRU算法,InnoDB
使用了一种技术来最小化缓冲池中从未访问过的数据量。目标是确保频繁访问(“热”)页面在缓冲池中保持, 即使读前和全表扫描将新块带入缓冲池中,这些块可能或可能不被访问。
新读取的块插入LRU列表的中间。所有新读取的页面都插入默认在LRU列表的末尾的3/8
处。这些页面在第一次从缓冲池中访问时被移动到列表的前端(最近使用的结尾)。因此,从未访问过的页面永远不会出现在列表的前端部分,并且“淘汰”更快地淘汰,而不是使用严格LRU方法。这一安排将LRU列表分成两个部分,其中下游插入点以下的页面被认为是“老”,并且是LRU淘汰的可取目标。
关于InnoDB缓冲池的内部工作和LRU算法的详细信息,请见第17.5.1节,“缓冲池”。
您可以控制LRU列表中的插入点,并选择是否将InnoDB
应用于由表或索引扫描带入缓冲池的块。配置参数innodb_old_blocks_pct
控制LRU列表中的“old”块百分比。默认值为innodb_old_blocks_pct
375
(缓冲池中的新页面会很快被淘汰)到95
(只保留5%的缓冲池用于热页,使算法接近LRU策略)。
避免读取前导优化可以避免由表或索引扫描引起的问题。在这些扫描中,数据页面通常在快速 succession访问一次,然后再无需访问。配置参数innodb_old_blocks_time
指定了在首次访问页面后可以访问该页面的时间窗口(以毫秒为单位)。默认值为innodb_old_blocks_time
1000
。增加该值使更多和更多块更快地从缓冲池中淘汰。
Both innodb_old_blocks_pct
和innodb_old_blocks_time
可以在 MySQL 选项文件 (my.cnf
或 my.ini
) 中指定或在运行时使用SET GLOBAL
语句更改。更改值需要具有足够的权限以设置全局系统变量。请参阅第7.1.9.1节,“系统变量权限”。
为了帮助您评估这些参数的影响,SHOW ENGINE INNODB STATUS
语句报告缓冲池统计信息。详细信息请参阅使用 InnoDB 标准监控器监控缓冲池。
由于这些参数的影响取决于您的硬件配置、数据和工作负载的细节,因此在任何性能关键或生产环境中更改这些设置之前,总是要进行基准测试以验证其有效性。
在混合工作负载中,其中大多数活动是 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
无法获得足够的性能改进,请进行自己的 benchmarks以确定最优值。