用多个数据缓存池
· 默认情况下,数据缓存中只存在一个(默认)缓存池,有可能出现这样的情形,某个用户程序偶尔存取一个很少使用的大表(非全表扫描),将缓存中其它用户经常使用的缓存块挤出,为了解决这个问题,可以定义多个缓存池,将段明确地指定给某个缓存池;
· 可以创建三种缓存池,根椐段被存取频率的不同将段指定给不同的池:
?nbsp; Keep Pool 用于存放你想在缓存中保留时间尽可能长的段;
?nbsp; Recycle Pool 用于存放你想在缓存中保留时间尽可能短的段;
?nbsp; Default Pool 存放不同于上面的其它的段;
· 与8i不同,9i各个池的内存分配是相互独立的;
· 确定哪些段适于存放在哪个缓存池中;
?nbsp; 要确定段与缓存池的对应关系,需要对应用程序,段及段的存取方式有一个整体的了解;
?nbsp; 了解目前已缓存的段的信息有助于确定段与缓存池的关系,V$BH, V$CACHE中都含有缓存的详细数据,下面两个查询作用类似,都能确定已缓存块的段名,所属用户名,段类型及缓存块数:
ü Select Obj.Owner,
Obj.Object_Name,
Obj.Object_Type,
Count(Distinct Bh.Block#) "Num of Buffers"
From V$bh Bh, Dba_Objects Obj
Where Bh.Objd = Obj.Object_Id
And Owner <> 'SYS'
Group By Obj.Owner, Obj.Object_Name, Obj.Object_Type;
ü Select u.Username,
c.Name,
c.Kind,
Count(Distinct c.Block#) "Num of Buffers"
From V$cache c, Dba_Users u
Where c.Owner# = u.User_Id
And u.Username <> 'SYS'
Group By u.Username, c.Name, c.Kind
?nbsp; 推荐经常使用且小于默认缓存池10%的段置于Keep池中;
?nbsp; 推荐只由个别事务使用且大于默认缓存池200%的段置于Recycle池中;
· 确定每个池的合适大小;在确定了段和各个池的对应关系后,可以通过DBA_SEGMENTS.BLOCKS查出对应池的段块之和,计算出各个池占用比例,再根椐缓存池的总大小可以确定每个池的大小;在末经精确计算的情况下,ORACLE推荐先按下面的比例为各个池分配空间:Default Pool 60%, Keep Pool 30%, Recycle Pool 10%。
· 创建缓存池;根椐前面提到的方法,动态或手工更改这三个参数(DB_CACHE_SIZE, DB_KEEP_CACHE_SIZE, DB_RECYCLE_CACHE_SIZE),可以创建缓存池;
· 将段指定给缓存池;
?nbsp; 可以在创建段时指定缓存池:Create … STORAGE ( BUFFER_POOL pool);
?nbsp; 也可以更改段的缓存池属性:Alter … STORAGE ( BUFFER_POOL pool);
?nbsp; 上面的pool可选值为KEEP, RECYCLE, DEFAULT(默认值);
?nbsp; DBA_SEGMENTS.BUFFER_POOL字段可以查到段的缓存池属性;
?nbsp; 更改段的缓存池属性并不会立即生效,需等到段下一次从磁盘载入缓存池时才能生效。
· 监控各个缓存池的性能;
?nbsp; V$BUFFER_POOL性能视图: Name(缓存池的名字), Block_Size(池的块大小,Byte), Current_Size(缓存池的当前大小,M)。
?nbsp; V$BUFFER_POOL_STATISTICS,包含每个缓存池的相关统计,可用来计算单独缓存池的命中率,重要的字段如下:
ü NAME
ü DB_BLOCK_GETS
ü CONSISTENT_GETS
ü PHYSICAL_READS
ü FREE_BUFFER_INSPECTED
ü BUFFER_BUSY_WAITS
ü FREE_BUFFER_WAITS
ü Select Name "Buffer Pool",
1 - (Physical_Reads / (Db_Block_Gets + Consistent_Gets)) "Hit Ratio"
From V$buffer_Pool_Statistics
Where Db_Block_Gets + Consistent_Gets > 0;
ü 经过调整后各个缓存池的命中率,Keep池的应该很高,Recycle池的应该很低,Default池应该为70~80%。
· 命中率高并不总是代表性能好;
?nbsp; 单纯的缓存命中率高并不代表缓存的性能很好,在RBO下,不正确的建立索引可能导致性能低下而缓存命中率却相当高,比如在一个经常使用表的低集势栏位上建二叉树索引就可能出现这种情形,系统不停而低效地扫描索引,导致出现虚高的缓存命中率;
?nbsp; 通过分析V$BH,V$CACHE的查询结果,结合对应用程序工作方式的理解,可以发现这种情况;
?nbsp; 按下面的处理可以消除这种可能:
ü 收集方案的统计并使用基于CBO的优化器;
ü 创建在Where条件中使用率高的栏位的柱状图统计;
ü 正确地使用多个缓存池。
第五章 调整数据缓存 5.其它提高数据缓存性能的方法
将小表CACHE到数据缓存
· 在多个缓存池的配置下,每个缓存池都是由独立的LRU算法来管理的,通常情况下刚存取的块都是放在LRU列表的开始端,而FTS(全表扫描)例外,刚读入的块放在LRU列表的末端;
· 上述算法会产生如下一些困境:CBO在读取一些小表或者读取表中的较多数据时会使用FTS,这时,即使这些表使用频率很高,也会因为上面提到的原因而很快被老化,在下次用到时又得重新读入;
· 为了解决这个难题,引进了Cache表的概念,将表设为Cache后,对表的FTS不再是将块放在LRU列表的末端,而是置于LRU列表的开始端;
· 有下面三种方法将表设为Cache:
ü 创建时指定CACHE关键字:Create table … cache;
ü 更改时指定CACHE关键字:Alter table … cache;
ü 查询时指定CACHE hint:select /*+ cache */ * from …;
· 从DBA_TABLES.CACHE字段可以查到由前两种方法设置的表的CACHE属性。
绕过缓存池
· 下面两种特定的操作可以绕过缓存池,读入的数据块不进入数据缓存,而存放在内存中由用户服务器进程控制的其它区域(UGA,PGA?):
ü Sort Direct Writes(第八章调整IO时会讲到);
ü Parallel DML(由多个服务器进程来执行一个DML操作,只有当系统中有多个CPU,多个IO子系统以及足够内存时才可考虑作这样的设置,并行DML超出本书讨论的范围)。
正确地使用索引
· 不正确的全表扫描会极大地降低数据缓存的命中率,创建正确的索引后可以提高数据缓存性能;
· 建议尽可能地在外键上创建索引,这可以提高多表连接的效率。
阅读(375) | 评论(0) | 转发(0) |