在Buffer Cache中自动大表缓存

约翰,在A银行做DBA。凯特琳,新的首席技术官,她正在为数据库性能问题由于长的I/O响应时间而沮丧。为了提高性能,她希望增加数据库实例的缓冲区缓存,以便在缓存中缓存更多的数据,从而减少了频繁需要去读磁盘。戴比,系统开发工程师,经历了很多这样的问题在她的职业生涯中,她解释说,“我们的应用有很多全表扫描,数据库的全表扫描使用的是直接路径读取(DPR)在表中的数据块,不做缓冲区高速缓存。”因此,添加物理内存到服务器后,增加缓冲区缓存,是不会帮助,因为缓冲区没有用。应用程序可以通过加hits跳过DPRs,使用缓冲区高速缓存,但在所有的应用需要修改成千上万的查询,这将是一个非常昂贵和耗时的过程,没有人愿意接受这种解决方案。为了提高全表扫描性能的唯一途径,是提高I/O子系统的吞吐量,例如使用闪存存储,但是闪存比较昂贵。
约翰向他们提出建议:在Oracle数据库12c(12.1.0.2)发布一个新功能可以使全表扫描被加载和保存在一个大的缓冲区高速缓存中。

为什么不缓存全表扫描?

在约翰解释新的功能之前,办公室里的每个人都想知道为什么一个完整的表扫描不会使用缓冲区缓存。当一个连接到数据库实例的会话从表中选择数据时,数据库服务器进程从磁盘读取适当的数据块,并默认地将它们放入缓冲区缓存中。每个块进入缓冲区中的缓冲中。原因很简单:如果另一个会话要访问这些块中的一些数据,它可以从缓存区查询,速度远远快于从磁盘上读取。缓冲区的缓存大小是有限的,通常小于整个数据库,所以当缓存满了,一个新的数据块要进来,数据库迫使旧的缓冲区,很长一段时间没有被访问的块被覆盖。约翰继续解释,考虑选择表的所有块的全表扫描查询的情况。如果该表非常大,它的块将消耗缓冲区缓存的很大一部分,迫使其他表的块被覆盖。这是不可能的,一个大表的所有块将被定期访问,所以在缓存中的那些块实际上并没有帮助性能。但是,强制讲其他表的块,尤其是受欢迎的块,挤出缓存区,会降低数据库中的应用程序的整体性能。这就是为什么,数据库不加载全表扫描到缓冲区缓存中的原因。

Temperature
大家对约翰为什么全表扫描不缓存高速缓存的原因的解释感到非常满意,但是,凯特琳,有另一个问题:如何决定Oracle数据库缓冲区高速缓存中的数据块的去或留?

约翰解释说,传统的数据库实例使用最近最少使用(LRU)列表来跟踪多久前在缓冲区高速缓存缓冲区的访问。当一个缓冲区的块第一次访问,它被放在LRU列表的头部。随着时间的推移,当缓冲区中的其他块被会话访问时,他们会移动到LRU列表头部,这会导致原始的缓冲区块从列表的头部向下滑动。当原始缓冲区块再次被访问时,它会移动到LRU列表的头部,但如果它被不访问,它一路下降到底部,并最终被从列表中移除掉。在这一点上,缓冲区的块将从缓存中移除。实际过程中,约翰赶忙补充,稍微复杂一点,因为实例还考虑其他因素,如多少次缓冲被触动的(通过一个叫触摸计数的计数器)。

但在Oracle数据库12c(12.1.0.2)中, 全表扫描可以缓存到缓冲区中:数据库有一个新的度量,温度,用于识别一个对象的受欢迎度。访问的对象的块越多,该对象的温度越高。而且由于温度是基于对象的,而不是在块上,它是一个更准确的衡量表的受欢迎度。
Big table

现在,利用新的特性,戴比可以缓存大表,这个新的功能,约翰描述为“自动大表缓存”。

但戴比看起来持怀疑态度。数据库是巨大的,缓冲区高速缓存尽管较大,仍然比数据库大小小得多。事实上,有一些表是相当大的。当他们被加载到缓冲区缓存中,他们将迫使很多流行的缓冲区的块被覆盖。所以,她沉思着,仍然存在风险。

风险仍然潜伏,约翰同意。因此,而不是冒险整个缓冲区缓存,数据库只是使一部分被用于缓存大表。这是由初始化参数控制的。戴比想把高达百分之40的用于此目的的缓冲区,所以约翰用以下SQL语句:
SQL>alter system set db_big_table_cache_percent_target = 40;
这将留出百分之40的缓冲区缓存用于大表缓存。其他百分之60将不会被大表的全表扫描所使用,所以流行的缓冲区块仍然可以存在在缓冲区中。这是一个动态参数,所以约翰不用重启数据库,即可重复效果演示。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/01473ca9449a51e6992e5873e2e54c4e.html