Chinaunix首页 | 论坛 | 博客
  • 博客访问: 153613
  • 博文数量: 51
  • 博客积分: 1545
  • 博客等级: 上尉
  • 技术积分: 600
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-31 10:20
文章分类

全部博文(51)

文章存档

2011年(3)

2010年(48)

我的朋友

分类: Oracle

2010-03-16 10:27:30

Oracle数据库的缓存命中率

数据库缓存(Block Buffer)对于Oracle数据库的运转和性能起着非常关键的作用,它占据Oracle数据库SGA(系统共享内存区)的主要部分。Oracle数据库通过使用LRU算法,将最近访问的数据块存放到缓存中,从而使对磁盘数据的访问效率最大优化到接近于内存访问的速度。由于数据库应用的核心操作就是数据的访问和处理,因此如果应用系统访问的大部分数据块已在缓存中,也就是数据在缓存中命中,那么应用在数据访问上的磁盘I /O等待和瓶颈将可以消除。然而内存相对于现代大部分数据库而言是非常有限的,由此数据库缓存的有效使用是非常重要的。

数据库缓存并非越大越好

Oracle文档对于数据库缓存命中率的定义为:

Hit Ratio = 1 - (physical reads / (db block gets + consistent gets))。

相对而言,不命中意味着需要执行磁盘访问。从这个计算公式可以看出,数据库缓存命中率准确地讲应称为数据块读命中率。也就是说,命中率仅包括缓存读操作而不包括写操作。不幸的是,由于语义上的模糊,使我们在许多时候将缓存命中率理解为数据库缓存读写操作的命中率。因此,我们经常会这样认为,如果不命中率减少一半,相应地系统在读写数据块方面的I/O操作也会减少一半。

在3、4年前,高端Unix服务器的内存配置一般不会超过4GB,数据库规模一般也在几个G到几十个G之间,SGA的配置一般在1G左右。而到了2002年,工作组级的服务器如Sun的V880标准配置就有4GB内存,今天,数据库的规模已经上升到100GB到1TB之间,配置4GB或更大的SGA区已成为许多管理员的选择。在这种趋势下,配置多大的SGA比较合适成了一个需要考虑的问题。由于SGA区越大意味着有更多的块可以保留在内存中,进而意味着数据库可以获得更高的缓存命中率和更好的应用程序响应时间,那么是不是缓存越大越好呢?因为服务器内存毕竟是昂贵的,获得理想的投资收益比是这个问题考虑的基础。

首先,与任何类型的缓存一样,缓存的合适尺寸取决于最频繁访问的数据集合(工作集)的大小,这个数值就是数据库缓存配置的一个临界值。当数据库缓存的大小超过这个临界值后,数据库缓存命中率随缓存加大而上升的比率将变得非常缓慢,应用程序响应速度的改进也变得不明显;在此之后,要增加几个百分点的命中率,也许需要添加更大量的内存。工作集的大小则由应用程序的数据访问模式决定,它与数据库的规模并没有直接的关联。一个非常庞大的数据库,其中一般存在着较大比例的静态数据,同时也许还有较大量的只写数据,它们在平时被访问的频率非常低;而真正被应用系统频繁访问的数据也许只有非常小的一部分,只要能确保这部分数据被缓存在内存中,数据库缓存的作用也就获得了充分发挥,对于访问频度非常低的数据缓存是没有太大意义的。因此合适的数据库缓存大小取决于应用系统数据访问的分布程度,对于完全随机分布的访问模式,除非将整个数据库缓存到内存中,否则扩大缓存配置是不会有太大效果的。我们的目标则是在保证理想的应用系统响应速度前提下,尽量节省不必要的硬件投资。

当然,一个生产系统投入使用后,其硬件配置是不可能轻易改变的。随着系统运行时间的推移,新的应用程序可能会不断开发出来并投入运行,它们将与Oracle数据库共同分享系统内存。当系统内存压力达到一定程度而出现频繁页面交换时,我们可能需要考虑通过减小Oracle数据库SGA区来缓解内存紧张。当进一步减小SGA区而造成数据库系能下降时,我们所要考虑的将是对系统内存进行扩容。

另一方面,Oracle对Buffer Cache通过使用一系列的链表来管理,数据块通过Hash算法定位到相应的链表中;数据库缓存越大,需要管理的数据库块也越多,相应地管理庞大数量内存块的开销将增大。如对于16GB的Buffer Cache和8k的Block Size,将有2097152个数据块需要管理。也许当SGA达到一定规模时,这种开销所产生的负面影响将显现出来,在配置大型SGA前,有必要进行相应的性能测试。

缓存命中率并非越高越好

也许任何一个DBA都知道,在实际生产系统中,一个非常低的命中率的确意味着系统配置或应用存在严重问题;但不幸的是,大多数人却不知道一个非常高(大于99%)的缓存命中率也往往同样意味着应用中存在严重低效率的SQL语句,因为只有这些极差的SQL语句的存在,才有可能制造出如此之高的命中。

高水平的缓存命中率并不能代表系统拥有良好的性能,命中率与系统性能之间并没有直接的关系。许多非常差的系统拥有非常高的命中率,而命中率低的系统可以是运行得非常快的系统。而非常高的缓存命中率(99%以上)几乎意味着效率极差的SQL语句的存在。如果我们将提高命中率作为解决性能问题的首选途径,那么我们就会为系统增加内存并扩大数据库缓存配置,而这种努力和投入的结果往往会令人失望;因为实际中的绝大多数性能问题是低劣的SQL所造成,而依赖扩大缓存配置来改善这些语句的执行效率显然是不会有太大帮助的。实际上,命中率最大用处在新系统的测试调整阶段,它可以帮助我们评估系统所需的缓存配置。当系统投入实际运行后,对于具体性能问题的处理则需要对系统进行会话事件级的分析,如果仍然通过命中率的角度来分析的话,将极有可能陷入盲目和不确定的挣扎中。不幸的是,大多数人在进行Oracle数据库性能优化时,只有当系统的缓存命中率在95%以上而且问题仍然无法解决时,才会开始考虑应用程序一级的诊断和调整。

说到这里,也许读者会产生困惑,如果不使用命中率来作为解决性能问题的方法,那又该使用何种方法?根据我的经历,通过分析存在问题的进程对应的等待事件和SQL语句是最为有效和直接的途径;它可以通过设置相应进程的trace(10046)事件,然后分析trace文件来实现。实时的系统监控则可以通过查询v$session_wait、v$session、v$sqltext视图来获取对等的数据。

数据库缓存与应用的访问模式相关

总的来说,什么样的数据库缓存命中率和多大的缓存才是合适的取决于应用系统的数据访问模式。对于数据访问不均衡的系统(现实中的大部分情况),可能较小的缓存就可以获得理想的命中率;而对于数据访问非常均衡的系统,非常大的缓存配置也许都难以有70%以上的命中率。对于后一种情况,除了在数据库级和应用程序上进行必要的优化,如使用多Buffer Cache功能确保参照表访问的完全命中外,必需规划、构建一个高效的I/O子系统,以为Oracle的数据读写提供最短的平均服务时间。我们所要需要做的是确保数据库缓存能够保留系统运行时重复访问的数据构成的工作集,另外在根据实际数据读写需求为其它部分数据块分配相应的缓存。如果结合Oracle8的多缓存功能,将以全表扫描方式访问的大表放入RECYCLE POOL,系统性能将会有很好的改善。

配置过大的数据库缓存常常会掩盖应用程序中存在的严重性能问题,这将延后问题的发现,增加应用调优的复杂度。实际上在绝大多数情况下,我们可以通过应用程序的SQL语句和业务逻辑算法的优化,极大提高应用程序的响应速度,同时大幅度降低系统负荷,而不需要被追加投资、系统扩容等复杂而漫长的解决方案所困扰。

阅读(1317) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~