oracle cache table(4)

jss001發表於2009-02-19
下面說明KEEP池快取的特點,先看一下查詢的結果:
SQL> SELECT COUNT(*) FROM T2;
COUNT(*)
----------
167011

Statistics
--------------
0 recursive calls
0 db block gets
4839 consistent gets
4829 physical reads
0 redo size
381 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

SQL> SELECT OBJECT_NAME, A.STATUS, COUNT(*)
2 FROM V$BH A, USER_OBJECTS B
3 WHERE A.OBJD = B.OBJECT_ID
4 AND OBJECT_NAME IN ('T', 'T2')
5 GROUP BY OBJECT_NAME, A.STATUS;
OBJECT_NAME STATU COUNT(*)
------------------------------
T xcur 3268
T2 xcur 4829
SQL> SELECT COUNT(*) FROM T;
COUNT(*)
----------
334022

Statistics
-----------------
0 recursive calls
0 db block gets
9666 consistent gets
9655 physical reads
0 redo size
381 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

對於第一個查詢全部物理讀比較好理解,這是由於當時KEEP池中的空間被T表佔滿了,隱藏這時候對T2的查詢需要從
物理磁碟讀取。執行完這個查詢,可以發現,T2表全部放入快取中,T表的資料被替換出一部分,還有3000多個BLOCK
儲存在KEEP池中。但是對T的查詢確全部由物理讀組成,而KEEP池中的快取沒有起作用。
對於普通的DEFAULT池,Oracle使用的是最近最少使用演算法,在記憶體中有一個類似連結串列的結構。當DB_CACHE填滿後,
Oracle會從將這個連結串列的最少使用端交換出去,用來存放新的資料。而且會根據新的資料的性質,選擇把新的資料
放到最多使用端還是最少使用端。
如果DB_CACHE滿後,執行的是索引掃描,則Oracle認為需要快取這些資料,因此會清空最少使用端的空間,存放索引掃
描的快取資料。如果是大表的全表掃描,則Oracle認為這些資料是很少需要被訪問的,因此清空最少使用端的空間放入
表掃描的快取資料後,仍然放回到最少使用端。
而KEEP池沒有采用這種演算法,KEEP池其實是一塊可用記憶體採用類似迴圈的演算法進行訪問。如果KEEP池裡面還有剩餘空間,
則新的資料會首先使用剩餘的空間,如果KEEP池已經儲存滿了,Oracle會從頭開始重用KEEP池。
這就是對T表的查詢導致了全部的物理讀的原因。由於T2表將T表中最初部分資料替換出KEEP,導致了查詢T表的時候,
開頭部分的資料無法找到,產生了物理讀後在KEEP池中替換了T表中間部分的資料,同樣的道理,讀取到T表中部的時候,
又把T表末尾的資料替換出去了。因此,執行完查詢發現,對T表查詢全部都是物理讀,KEEP池緩衝中的內容沒有起作用。

而且,由於T表的大小超過了KEEP池的大小,因此T表末尾部分的資料又會將開頭部分的資料替換出去,因此,再次對T表
查詢仍然全部都是物理讀。
SQL> SELECT COUNT(*) FROM T;
COUNT(*)
----------
334022
Statistics
--------------
0 recursive calls
0 db block gets
9666 consistent gets
9655 physical reads
0 redo size
381 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> SELECT COUNT(*) FROM T;
COUNT(*)
----------
334022

Statistics
-----------------
0 recursive calls
0 db block gets
9666 consistent gets
9655 physical reads
0 redo size
381 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
只有當對T表的掃描的塊小於KEEP池的大小時,才能保證快取可以被利用。
SQL> SELECT COUNT(*) FROM T WHERE ROWNUM < 100000;
COUNT(*)
----------
99999
Statistics
----------------
0 recursive calls
0 db block gets
3696 consistent gets
3695 physical reads
0 redo size
381 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> SELECT COUNT(*) FROM T WHERE ROWNUM < 100000;
COUNT(*)
----------
99999
Statistics
--------------
0 recursive calls
0 db block gets
3696 consistent gets
0 physical reads
0 redo size
381 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/18921899/viewspace-1017602/,如需轉載,請註明出處,否則將追究法律責任。

相關文章