oracle数据库:内存结构_笔记9
4.2.3块缓冲区缓存
Oracle将数据库块写至磁盘之前,或从磁盘读取数据库块,就会把这些数据库块存储在块缓冲区缓存(block buffer cache)中。如果太小,我们的查询就会永远也运行不完。如果太大,又会让其他进程饥饿。
在Oracle的较早版本中,只有一个块缓冲区缓存,所有段的所有块都放在这个区中。从Oracle8.0开始,可以把SGA中各个段的已缓存块放在3个位置上。
.默认池(default pool):所有段块一般都在这个池中缓存。这就是原先的缓冲区池。
.保持池(keep pool):按惯例,访问相当频繁的段会放在这个候选的缓冲区池中,如果把这些段放在默认缓冲区池中,尽管会频繁访问,但仍有可能因为其他段需要空间而老化(aging)。
.回收池(recycle pool):按惯例,访问很随机的大段可以放在这个候选的缓冲区池中,这些块会导致过量的缓冲区刷新输出,而且不会带来任何好处,因为等你想要再用这个块时,它可能已经老化退出了缓存。要把这些段与默认池和保持池中的段分开,这样就不会导致默认池和保持池中的块老化而退出缓存。
从Oracle Database 9i开始,除了默认池、保持池和回收池外,DBA还要考虑第4种可选的缓存:db_Nk_caches。增加这些缓存是为了支持数据库中多种不同的块大小。在Oracle Database 9i之前,数据库只有一种块大小。从Oracle Database 9i开始,数据库可以有一个默认的块大小,也就是默认池、保持池或回收池中存储的块的大小,还可以有最多4种非默认的块大小。
1、在缓冲区缓存中管理块
缓冲区缓存中的块裨上在一个位置上管理,但有两个不同的列表指向这些块。
.脏(dirty)块列表,其中的块需要由数据库块写入器(DBWn)写入磁盘
.非脏(nondirty)块列表
在Oracle 8.0及以前版本中,非脏块列表就是最近最少使用(Least Recently Used,LRU)列表。块按使用的顺序列出。在Oracle 8i及以后版本中,算法稍有修改。不再按物理顺序来维护块列表,Oracle采用了一种接触计数算法,如果命中缓存中的一个块,则会增加与之相关联的计数器。不是说每次命中这个块都会增加计数,而是大约每3秒一次。
X$BH表显示了块缓冲区缓存中块的有关信息。在这个表中可以看到,我们命中块时,接触计数会增加,可以对这个表运行以下查询,得到5个“当前最热的块”,并把这个信息与DBA_OBJECTS视图联结,得出这些块属于哪些段。
sys@ORCL>select tch,file#,dbablk,
2 case when obj=4294967295
3 then 'rbs/compat segment'
4 else (select max( '('||object_type||')' ||
5 owner || '.' || object_name) ||
6 decode( count(*),1,'','maybe!')
7 from dba_objects
8 where data_object_id=X.OBJ)
9 end what
10 from(
11 select tch,file#,dbablk,obj
12 from x$bh
13 where state <>0
14 order by tch desc
15 )x
16 where rownum <=5
17 /
TCH FILE# DBABLK
---------- ---------- ----------
WHAT
----------------------------------------------------------------------------------------------------
173 1 2017
(TABLE)SYS.JOB$
173 1 2016
(TABLE)SYS.JOB$
45 1 12312
(TABLE)SYS.SCHEDULER$_LIGHTWEIGHT_JOB
45 1 12217
(INDEX)SYS.SCHEDULER$_CLASS_PK
45 1 12225
(TABLE)SYS.SCHEDULER$_JOB
sys@ORCL>select data_object_id,count(*)
2 from dba_objects
3 where data_object_id is not null
4 group by data_object_id
5 having count(*) >1;
DATA_OBJECT_ID COUNT(*)
-------------- ----------
625 3
29 3
6 3
2 18
495 7
8 3
268 2
421 2
10 3
656 3
0 4
11 rows selected.
甚至对于重复查询的块,也可以观察Oracle如何递增这个块的接触计数。
sys@ORCL>select tch,file#,dbablk,DUMMY
2 from x$bh,(select dummy from dual)
3 where obj=(select data_object_id
4 from dba_objects
5 where object_name='DUAL'
6 and data_object_id is not null)
7 /
TCH FILE# DBABLK DUM
---------- ---------- ---------- ---
0 1 929 X
1 1 928 X
sys@ORCL>exec dbms_lock.sleep(3.2);
PL/SQL procedure successfully completed.
sys@ORCL>/
TCH FILE# DBABLK DUM
---------- ---------- ---------- ---
1 1 929 X
2 1 928 X
sys@ORCL>exec dbms_lock.sleep(3.2);
PL/SQL procedure successfully completed.
sys@ORCL>/
TCH FILE# DBABLK DUM
---------- ---------- ---------- ---
2 1 929 X
3 1 928 X
sys@ORCL>exec dbms_lock.sleep(3.2);
PL/SQL procedure successfully completed.
sys@ORCL>/
TCH FILE# DBABLK DUM
---------- ---------- ---------- ---
3 1 929 X
4 1 928 X
sys@ORCL>exec dbms_lock.sleep(3.2);
PL/SQL procedure successfully completed.
sys@ORCL>/
TCH FILE# DBABLK DUM
---------- ---------- ---------- ---
4 1 929 X
5 1 928 X
在Oracle 8i及以上版本中,块缓冲区不再像以前那样移到块列表的最前面;而是原地留在块列表中,只是递增它的接触计数。不过,过一段时间后,块会很自然地在列表中“移动”(不是物理地移动)。只是因为维护了多个指向块的列表,所以块会在这些列表间“移动”。例如,已修改的块由脏列表(要由DBWn写至磁盘)。过一段时间要重用块时,如果缓冲区缓存满了,就要将接触计数较小的某个块释放,将其“放回到”新数据块列表的接近于中间的位置。
http://www.52ij.com/jishu/5169.htmloracle数据库:内存结构_笔记8
本文来源 我爱IT技术网 http://www.52ij.com/jishu/5170.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
