【江枫】Shared Pool空间管理算法的演进(二)

上一篇 / 下一篇  2008-04-21 13:32:25

根据前面的描述,我们知道Oracle9i之前共享池的空间管理算法对于大内存和多并发的性能存在问题,也很容易的想到两个解决问题的方向,一个是争加Shared Pool Latch也就是Freelist的个数,使同一时刻可以有更多的进程执行空间搜索操作。另外一个是增加Freelist上的Bucket个数,从而减短单个链表的长度。实际上Oracle9i的Shared Pool空间管理算法就是按照这两个思路来进行改进的。在Oracle9i中,Shared Pool Latch增加到最多可以有7个child latch,每个Freelist上的Bucket则一举增加到了255个,每个Bucket上free chunk的范围分布为:

Bucket 0~199 容纳size以 4 递增
Bucket 200~249 容纳size以 64 递增
Bucket 249: 4012 ~4107 = 96
Bucket 250: 4108 ~8203 = 4096
Bucket 251: 8204 ~16395 = 8192
Bucket 252: 16396~32779 = 16384
Bucket 253: 32780~65547 = 32768
Bucket 254: >=65548

更多的bucket,意味着每个bucket上的链表长度将大大的缩短,尤其在bucket0~199上,每个Bucket上的chunk大小以4字节递增,将小chunk尽量分布到更多的Bucket上去,从而解决9i之前搜索小chunk时的性能问题,而大多数时候,系统都是在为小对象搜索空间,解决了大多数时候的性能问题,也就解决了整个系统的问题,这是系统优化的一个重要方法。

另外一个方面,是否全部启用7个child latch,是需要根据系统环境来确定的。每个child latch可以保护一个Freelist,每个Freelist可以管理一部分的空间,这样就可以把一个大的Shared Pool分割成多个小的sub pool,对于大的东西进行切分管理,也是系统优化的一种重要手段,这种思想在我们生活中也随处可见。Oracle9i在默认情况下,按照4个CPU可以切分一个sub pool,每个sub pool的最小边界是128M。也就是说,假如系统有12颗CPU,200M的Shared Pool只会有一个sub pool。如果Shared Pool增加到300M,则会有两个大小为150M的sub pool,如果增加到500M,则有3个166M的sub pool。在为对象搜索可用空间的时候,如果在一个sub pool中找不到合适大小的chunk,也不会再切换到其他sub pool了,这个时候即使其他sub pool还有大量的可用空间,也会报Ora-04031错误。

当然,Oracle的算法会尽量的保证各个sub pool的可用空间在一个平衡状态,sub pool和Bucket的个数取的都是质数,也是基于均匀分布的考虑,至于为什么质数可以均匀分布,则需要牵扯到数学知识了,这里就不讨论啦(其实是我也不清楚,好像跟取模运算有关,哪位知道的欢迎留言指教一下^_^)。但是例外总是有发生的,比如我们的一个实际案例,报ora-04031的时候,整个共享池还有120M的可用空间,但是其中一个子池只有不到5M了。而且128M的最小边界也有点太小了,可能由于Oracle9i中是第一次引入多个sub pool的管理算法,缺乏足够的经验和数据参照,这些默认设置还是有诸多可以商量的地方的。

可以通过加大Shared Pool来间接的增加每个sub pool的大小,但是这有一个问题,在sub pool的个数没有达到系统限制的最大个数之前,加大Shared Pool的大小,并不一定会导致单个sub pool的增加,比如一个系统的共享池原来是800M,6个sub pool,每个是133M,后来增加到900M,但是sub pool也增加到了7个,每个sub pool反倒只有128M了。当然,sub pool的个数多了,可以减少每个子池的压力。但还是无法解决单个子池空间耗净的情况。如果系统内存不是非常的紧张,可以继续加大,甚至可以考虑牺牲一点Buffer Cache的空间,因为最多只能有7个sub pool,如果Shared Pool加大到2G,每个sub pool也就有292M。而且oracle9i由于大幅争加了Bucket的个数,共享池大一点也不会造成太大的额外压力。

另外,Sub Pool的个数也可以由一个隐含参数来进行手工调整:_kghdsidx_count,据Oracle supporter的说法,这个参数的调整基本上是没有风险的。但是一般情况下,还是不推荐修改隐含参数,尤其是生产库。也可以通过查询该参数的值来看当前系统中sub pool个数,隐含参数的查询可以通过关联x$ksppi和x$ksppcv获得,具体的SQL这里就不列了,网上到处都是。我的习惯一般是根据这两个内部表建一个all_parameters的视图,然后查这个视图就比较方便了。

平时在statspack中也可以多关注整个Shared Pool的空间使用率,如果过高比如到80%多了,则需要考虑是增加Shared Pool呢,还是由于应用的SQL绑定变量做得不好导致无谓的浪费了太多共享池空间,如果是应用的问题,则需要优先调整应用。

--EOF--


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

我的栏目

日历

« 2008-07-25  
  12345
6789101112
13141516171819
20212223242526
2728293031  

数据统计

  • 访问量: 10664
  • 日志数: 110
  • 建立时间: 2008-03-27
  • 更新时间: 2008-06-24

RSS订阅

Open Toolbar