ORACLE--SGA之數據緩衝區(Data Buffer)
暨上通過預編譯闡述道共享池最後到SGA,這裏進一步說明一下SGA中另一個大塊,數據緩衝區,攜帶提及一點數據文件和表空間,後續專門會說明這塊。
首先了解下SGA種大致有那些東西,這些東西隨著數據庫版本的增加會有所增加,不過大致上應該一致,這也是基本所有的體係結構都會描述的東西:
在認識數據緩衝區前,先記住幾個常用的視圖:
X$BH、GV$BH、V$BH、V$FIXED_TABLE、V$FIXED_VIEW_DEFINITION、DICT、DICT_COLUMNS。
以及兩個包:DBMS_SPACE 和 DBMS_ROWID的一些常用內容,在後麵會逐漸用到時說明部分使用方式,不過還是先要創建一個表,不然什麼測試工作也做不了:
在一個用戶下創建一個表:
CREATE TABLE TEST_OBJECTS
AS SELECT * FROM USER_OBJECTS;
如果那個用戶下沒有什麼對象,那就多複製幾次數據,才能填充一些數據,數據成倍增長:
INSERT INTO TEST_OBJECTS
SELECT * FROM TEST_OBJECTS;
COMMIT;
此時第一個,常規使用下,一個常用的對象就是ROWID,那麼看下它由哪幾部分組成:
對象編號、文件編號、文件內塊號、塊內部行號碼,我們看下一張表內部每條數據的這些信息:
SQL>SELECT dbms_rowid.rowid_relative_fno(ROWID) "文件編號",
dbms_rowid.rowid_object(ROWID) "對象編號",
dbms_rowid.rowid_block_number(ROWID) "塊編號",
dbms_rowid.rowid_row_number(ROWID) "塊內部行號碼"
FROM TEST_OBJECTS t;
文件編號 對象編號 塊編號 塊內部行號碼
---------- ---------- ---------- ------------
4 54646 588 0
4 54646 588 1
4 54646 588 2
4 54646 588 3
4 54646 588 4
4 54646 588 5
4 54646 588 6
4 54646 588 7
4 54646 588 8
4 54646 588 9
4 54646 588 10
4 54646 588 11
4 54646 588 12
4 54646 588 13
4 54646 588 14
4 54646 588 15
4 54646 589 0
4 54646 589 1
4 54646 589 2
4 54646 589 3
其實對象編號是永遠不會變化的,一般情況下也在同一個文件中,所以主要看的是BLOCK的信息。
付:文件號是對應數據文件的編號,對應視圖DBA_DATA_FILES的FILE_ID字段。
對象編號是對象在整個數據庫的唯一標識,對應DBA_OBJECTS的OBJECT_ID字段。
此時通過分析表:
BEGIN
dbms_stats.gather_table_stats('SCOTT','TEST_OBJECTS');
END;
後查詢統計信息:
SELECT BLOCKS, NUM_ROWS
FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_OBJECTS';
BLOCKS NUM_ROWS
---------- ----------
16 1024
再查詢用戶段信息:
SQL> SELECT t.segment_name,t.blocks FROM USER_SEGMENTS T
2 WHERE T.segment_name='TEST_OBJECTS';
SEGMENT_NAME BLOCKS
-------------------------------------------------------------------------------- ----------
TEST_OBJECTS 16
在查詢根據上述統計出來的信息:
SQL> SELECT COUNT(DISTINCT dbms_rowid.rowid_block_number(ROWID))
2 FROM TEST_OBJECTS;
COUNT(DISTINCTDBMS_ROWID.ROWID
------------------------------
13
為什麼不一樣,因為內部有保留塊,記錄表頭、位圖信息,數據庫始終比這個實際的段要小,通過測試可以發現,每次增長都會以8個塊增長,但是數據實際的值,記錄實際數據塊大小,當發現兩者之和大於實際大小,就需要擴展空間了。
上麵有點開場白,這裏再想下試驗前需要明白,數據緩衝區用於在數據從磁盤中讀取數據後到內存是以“塊”為基本單位,不論塊中存儲多少行數據,分別有“單塊讀”和“多塊讀”兩種方式,讀入內存後,此時未了避免下次再重磁盤上去讀取,減少磁盤讀取開銷,此時將這些塊放入內存中,並采用LRU鏈表進行管理(ORACLE 8I後並非完全的LRU算法),當對這些數據修改時,內存采用一致性讀塊進行管理(一個塊最多對應6個一致性讀塊),當數據緩衝區不夠用的時候,就會將接使用較少的部分提取出來,將其替換到磁盤上去(其實就是在內存中將其指針刪除),為簡單證明這個情況,我們需要做一個簡單試驗,剛才創建的表,我們找幾個塊出來做實驗(588塊和589塊吧,對象編號上述已經查詢出來是:54646,文件號也能通過上述看出是:),我們首先通過X$BH視圖查看其實用情況。
--X$BH需要在DBA用戶下才可以使用,即使在全局數據字典:
V$FIXED_TABLE、V$FIXED_VIEW_DEFINITION、DICT
也找不到他的身影,因為它基本不被外界使用;
順便說下全局視圖:
V$FIXED_TABLE 查詢所有的V$視圖定義和X$視圖信息,GV$視圖普遍為集群類使用。
V$FIXED_VIEW_DEFINITION 查詢所有V$視圖、V$的定義部分
DICT 查詢到所有字典的字典列表信息
三者很多信息都是重複的,關鍵字段有些變化。
通過V$FIXED_VIEW_DEFINITION視圖可以找到X$BH定義了GV$BH,由GV$BH的大部分字段組成了V$BH。
另外如果要查詢兩個塊下麵的數據如何查詢:
定位一下這兩個快不是很好查,怎麼查詢呢,因為隻是實驗,也不用管太多,隻要能得到要的結論即可,此時塊信息是需要588~599兩個塊,那麼我們怎麼查詢數據呢,通過ROWID,就需要DBMS_ROWID包來創建: ROWID >= DBMS_ROWID.ROWID_CREATE(1, 54646, 4, 588, 0)
AND ROWID < DBMS_ROWID.ROWID_CREATE(1, 54646, 4, 600, 0);
DBMS_ROWID.ROWID_CREATE用於創建ROWID,參數按順序為:類型(直接寫1即可),對象編號、文件編號、文件內塊號、塊內行號。
扯遠了,回到話題,開始試驗下:
而X$BH視圖看下有那些字段(一看看花眼了,找到想要的就行了):
SQL> DESC X$BH
名稱
-------------
ADDR
INDX
INST_ID
HLADDR
BLSIZ
NXT_HASH
PRV_HASH
NXT_REPL
PRV_REPL
FLAG
RFLAG
SFLAG
LRU_FLAG
TS#
FILE#
DBARFIL
DBABLK
CLASS
STATE
MODE_HELD
CHANGES
CSTATE
LE_ADDR
DIRTY_QUEUE
SET_DS
OBJ
BA
CR_SCN_BAS
CR_SCN_WRP
CR_XID_USN
CR_XID_SLT
CR_XID_SQN
CR_UBA_FIL
CR_UBA_BLK
CR_UBA_SEQ
CR_UBA_REC
CR_SFL
CR_CLS_BAS
CR_CLS_WRP
LRBA_SEQ
LRBA_BNO
HSCN_BAS
HSCN_WRP
HSUB_SCN
US_NXT
US_PRV
WA_NXT
WA_PRV
TCH
TIM
需要的字段有:文件號、對象編號、塊號、TOUCH熱度信息,分別對應字段:file#、obj、dbablk、tch信息,查看一下:
SQL> SELECT file#,dbablk,tch FROM x$bh
2 WHERE obj = 54646
3 AND dbablk in(588,589)
4 ORDER BY dbablk;
FILE# DBABLK TCH
---------- ---------- ----------
4 588 8
4 589 8
此時發現已經有一些操作,此時開始對第589塊上任意一行數據查詢(另起一個會話):
SELECT *
FROM TEST_OBJECTS T
WHERE ROWID = DBMS_ROWID.ROWID_CREATE(1, 54646, 4, 589, 0);
然後再執行上述SQL
SQL> /
FILE# DBABLK TCH
---------- ---------- ----------
4 588 8
4 589 9
有興趣可以多做幾次,每次都會有變化,注意,可能對同一個塊查詢出多條記錄,那是一致性讀的問題,很多漲塊信息也在裏麵。
然後再執行一下清空數據緩衝區的操作,其實就是清空熱點度的問題:
SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;
係統已更改。
SQL> SELECT file#,dbablk,tch FROM x$bh
2 WHERE obj = 54646
3 AND dbablk in(588,589)
4 ORDER BY dbablk;
FILE# DBABLK TCH
---------- ---------- ----------
4 588 0
4 589 0
4 589 0
此時熱點度的TCH都是0了,同樣的方式可以去查詢V$BH視圖,V$BH中沒有TCH這個字段,對應數據文件字段還是file#,而塊字段是block#,提供一個狀態字段status和flag字段來源其它視圖,status指明被instance共享、專用、還是一致性讀塊、空閑塊;flag按照和1、16、1536等等進行按位求與運算(通過函數bitand)得到塊內部的信息,如是否為髒塊、是否為臨時塊等等信息。
數據讀取過程有兩種方式:單塊讀(db file sequential)和多塊讀(db file scattered read),所謂單塊讀就是每次IO隻讀取一塊到內存,主要看分布情況,一般我們用索引定位少量數據或者用ROWID定位少量數據時較多,但是也有其它情況,和多塊讀一起說明;多塊讀是一次讀入多個連續塊到內存中(一定是連續的),這個數據的上限是由參數db_file_multiblock_read_count參數指定,默認是16個塊,可以根據實際情況作相應調整,不過很多時候它是一個理想數字,一般達不到,因為當數據緩衝區不夠的時候會替換一些不常用的塊到磁盤中,此時數據塊在內存中的分布零散的,此時當在查詢某個數據範圍時,包含多個塊,但是這些塊在內存中非連續,那麼就會按照斷掉的部分到磁盤上去讀取,此時就會選擇單塊讀還是多塊讀了,此時較為消耗IO性能,最壞的情況是每個塊斷一塊,所以在業務層麵,對於多塊信息在考慮查詢過程中,保證和查詢中的多塊讀的參數差不多是較為理想的選擇(但是這個可能真的不好控製,不過應當有一定的理論計算值),否則在設計層麵上,平均性能差距會產生幾倍的差距。
另外對於常規小表並且經常查詢的或者些經常查詢的不太大的索引,此時我們習慣讓他們放入內存中,此時使用對表的屬性修改為內存表格即可:
ALTER TABLE <table_name> CACHE;
另外可以指定存放位置,默認情況下,ORACLE現在隻會給與一個db_cache_size,它是常規的數據緩衝區信息,其實數據緩衝區還有兩塊分別為:db_keep_cache_size為幾乎不會被替換出內存的區域,和db_recycle_cache_size幾乎使用完就會被替換出內存的區域(付:如果為ORACLE 9i以前,不包括ORACLE 9i使用的參數為:db_block_buffer、db_pool_keep、db_pool_recycle)。
查詢這幾個參信息:
show parameter db_cache_size;
show parameter db_keep_cache_size;
show parameter db_recycle_cache_size;
或者通過視圖:
SELECT * FROM v$buffer_pool_statistics;
若發現後兩者沒有數據則修改這記者的大小信息:
SQL>alter system set db_cache_size = 400M;
SQL>alter system set db_keep_cache_size = 150M;
SQL>alter system set db_recycle_cache_size = 50M;
這裏需要注意的是:若要增加後麵兩者,需要先減少前者的大小,因為數據緩衝區畢竟還是一個整體,另外你設置的大小未必是實際的大小,ORACLE會根據你的設置做相應的細節調整,調整完成後,可以SHOW PARAMETER查看大小變化。
如上述表需要設置到KEEP區域進行存儲,此時使用:
ALTER TABLE <table_name> STORAGE(BUFFER_POOL KEEP) cache;
同理其它區域分別設置:DEFAULT、RECYCLE,如果將一個已經是cache表修改為非cache表,此時將參數修改為nocache即可。
修改為cache表後,可以通過視圖查看:
SELECT name,owner,type
FROM v$db_object_cache where kept = 'YES'
AND NAME ='表名稱大寫';
或者查詢表的屬性信息查看:
SELECT a.cache,a.BUFFER_POOL,a.table_name
FROM user_tables a
WHERE a.table_name = ‘表名稱大寫’;
從數據緩衝區可以看出內部運作和讀取方式,根據實際情況中的一些便要設計中有一定用處,這也是一些基礎,在後麵文件管理(其實文件係統才是真正的數據庫,現在說的都是實例內部的信息,他們是完全不同的概念),和索引原理上結合企業也許會更加清楚吧。
關於下一次應該是涉及物理結構的文件係統或者實例另一部分PGA相關說明。。。。
最後更新:2017-04-02 05:21:05