對於'Consistent Gets',''Physical Reads'和'DB Block Gets'的理解和解釋

在Oracle的文檔中有這樣的解釋:
db block gets:Number of times a CURRENT block was requested.
consistent gets:Number of times a consistent read was requested for a block.
physical reads:Total number of data blocks read from disk. This number equals the value of "physical reads direct" plus all reads into buffer cache.
---------------------------------------------
針對以上3個概念進行的說明解釋及關係如下:
1、DB Block Gets(當前請求的塊數目)
當前模式塊意思就是在操作中正好提取的塊數目,而不是在一致性讀的情況下而產生的塊數。正常的情況下,一個查詢提取的塊是在查詢開始的那個時間點上存在的數據塊,當前塊是在這個時刻存在的數據塊,而不是在這個時間點之前或者之後的數據塊數目。

2、Consistent Gets(數據請求總數在回滾段Buffer中的數據一致性讀所需要的數據塊)
這裏的概念是在處理你這個操作的時候需要在一致性讀狀態上處理多少個塊,這些塊產生的主要原因是因爲由於在你查詢的過程中,由於其他會話對數據塊進行操作,而對所要查詢的塊有了修改,但是由於我們的查詢是在這些修改之前調用的,所以需要對回滾段中的數據塊的前映像進行查詢,以保證數據的一致性。這樣就產生了一致性讀。

3、Physical Reads(物理讀)
就是從磁盤上讀取數據塊的數量,其產生的主要原因是:
1、 在數據庫高速緩存中不存在這些塊
2、 全表掃描
3、 磁盤排序

它們三者之間的關係大致可概括爲:
邏輯讀指的是Oracle從內存讀到的數據塊數量。一般來說是'consistent gets' + 'db block gets'。當在內存中找不到所需的數據塊的話就需要從磁盤中獲取,於是就產生了'phsical reads'。

覺得還是不夠詳細,再補充一下:
db block gets :
number of data blocks read in CURRENT mode ie) not in a read consistent fashion, but the current version of the data blocks. 產生db_block_gets的主要方式:
1.DML like Update, Delete will need to access the blocks in the current mode for modification.
2.Most data dictionary calls are done in CURRENT mode.
3.Buffers are often retrieved in current mode for INSERT, UPDATE, and DELETE, and SELECT FOR UPDATE statements. Blocks must be requested in current mode in order to be changed.
4.Also certain classes of blocks, like segment header blocks are always requested in current mode.
5. this will happen when you're doing a FULL TABLE SCAN on a table or a FAST FULL SCAN on an index. In those cases, the segment header is read (usually multiple times for some unknown reason) in current mode.

在current mode模式下產生的對block的訪問叫db block gets,這些block在SGA中,不需要訪問硬盤。
db_block_gets counts logical reads in CURRENT mode in the buffer cache and also includes direct read blocks (sort-on-disk) blocks.
.
consistent gets :
number of data blocks accessed in READ CONSISTENT mode. When a block is requested in consistent mode, if any changes have been committed or made to that block since the requesting statement (or transaction) began, then they must be rolled back for the purposes of the read, to give a consistent view of the data at that time.(當數據庫是在consistent mode模式下被請求的,則假如該數據塊的數據修改是在查詢語句發出之後被提交的,則此查詢語句讀到該數據塊時,還必須爲本次查詢將數據回滾,得到查詢語句發出時該數據塊的值,以便給查詢給出一個與該查詢有關的所有數據塊的一致性視圖,這也就是oracle所說的一致性讀)   In order to maintain statement level read consistency, Oracle has to read the blocks in a consistent fashion(as of the snapshot SCN) and hence may fetch from rollback segments , which is also added to this statistic. Buffers are usually retrieved in consistent mode for queries. 如普通的select語句、索引訪問而引起的將數據讀入到buffer中(也可能爲physical read)或直接從buffer中讀數據。注意,DML語句也能引起consistent gets,如update tab1 set col_b='Hello world' where col_a=1;,因爲該語句需要找到需要被修改的所有數據塊,在找數據塊的過程中就會引起consistent gets
在Read consistent mode模式下產生的對block的訪問叫consistent gets

Session logical read is: The sum of "db block gets" plus "consistent gets".

db_block_changes:
db_block_changes counts modifications made to CURRENT blocks
'db block changes' = changes made to current blocks under LOGING ( UPDATE, INSERT, DELETE) + changes made to SORT blocks ( NOLOGING).

'consistent changes' :
changes made to block for CONSISTENT READ and changes made to SORT blocks

physical reads :
Physical( disk and/or filesystem page cache) reads. Basically those that cannot be satisfied by the cache and those that are direct reads.
Total number of data blocks read from disk. This number equals the value of "physical reads direct" (direct from disk, excludes buffer cache) plus all reads into buffer cache.


physical writes :
Total number of data blocks written to disk. This number equals the value of "physical writes direct" (Number of writes directly to disk, bypassing the buffer cache as in a direct load operation) plus all writes from buffer cache.

要注意Oracle 的physical read 與 physical writes並不總是等於硬盤真正意義上的物理讀與物理寫,因爲現在都存在操作系統高速緩存與磁盤子系統高速緩存,這樣及時I/O沒有被實際寫入磁盤,操作系統I/O子系統或磁盤系統也會確認爲一個成功的I/O,所以ORACLE 的physical read 與 physical writes並不是物理上發生讀寫的次數。


redo block size:
redo block size is platform specific. There is a method to determine the size by dumping the redo header, refer to note 154864.1. Redo blocks written does not include archive writes or multiplexed writes.

redo entries:
The redo log buffer is a circular buffer in the SGA that holds information about changes made to the database. This information is stored in redo entries. Redo entries contain the information necessary to reconstruct, or redo, changes made to the database . Redo entries are used for database recovery, if necessary.
Redo entries are copied by Oracle server processes from the user's memory space to the redo log buffer in the SGA. (this copy is what the statistic represents).


db block changes包含dml修改的block,也包含爲實現rollback功能而修改的block,但是不包含爲實現redo功能而修改的block。

the number of blocks visited = consistent gets + db block gets
the number of blocks visited相當與logical read,即從內存中都數據塊的次數。


做一個測試:
用下面語句取得統計信息:
select sid,value,name from v$sesstat x,v$statname y
where x.statistic#=y.statistic#
and ( name like '%db block%gets%' or name like '%consistent%gets%'
or name like '%consistent%change%' or name like '%db block%change%'
or name like '%physical writes%' or name like '%physical reads%'
or name = 'index fetch by key' or name like '%read%' or name like '%scans%'  
)
and sid = 12 and value > 0
order by value;


Lets take an example to illustrate relationship between 'db block gets' and 'db block changes' .

create table toto( i number);

select sid,value,name from v$sesstat x,v$statname y
where x.statistic#=y.statistic#
and ( name like '%db block%gets%' or name like '%consistent%gets%'
or name like '%consistent%change%' or name like '%db block%change%'
or name like '%physical writes%' or name like '%physical reads%'
or name = 'index fetch by key' or name like '%read%' or name like '%scans%'  
)
and sid = 12 and value > 0
order by value;

SID VALUE NAME
---------- ---------- ------------------------------
11 95 db block gets
11 108 db block changes
11 0 consistent changes

select count(*) from toto x, toto y, toto z;
COUNT(*)
----------
0

select sid,value,name from v$sesstat x,v$statname y
where x.statistic#=y.statistic#
and ( name like '%db block%gets%' or name like '%consistent%gets%'
or name like '%consistent%change%' or name like '%db block%change%'
or name like '%physical writes%' or name like '%physical reads%'
or name = 'index fetch by key' or name like '%read%' or name like '%scans%'  
)
and sid = 11 and value > 0
order by value

SID VALUE NAME
---------- ---------- ------------------------------
11 98 db block gets
11 108 db block changes
11 0 consistent changes

Here we can see that a select increment 'db block gets' by 3 and 'db block changes' remains the same : this illustrates that we can get block in current mode ( to have most recent information) without performing any changes." – 這也可以作爲current mode的定義。



下面這段寫的非常好,如果上面的還是不理解,則需要仔細的看一下!
A 'consistent get' is your server process telling the database "I need this dba (data block address) consistent with the point in time represented by this SCN, x."

So, lots of things can happen here. First, Oracle will look in the buffer cache for a CR (consistent read) buffer of the block that's consistent w/ the requested SCN. It may find it, if it does, that's counted as a 'consistent get' and either a 'consistent gets - no work' or 'consistent gets - cleanouts only', depending on whether the block needed to be cleaned out. (See V$SYSSTAT/V$SESSTAT for the statistics.) If it doesn't, it may take an existing CR buffer and roll it back further, or it may clone the current block and roll it back. If it needs to apply rollback (aka undo) then it will increment 'consistent gets' and either 'consistent gets - rollbacks only' or 'consistent gets - cleanouts and rollbacks'.

So, each 'consistent get' is your server process successfully getting access to the contents of a dba consistent w/ a particular SCN. This number should represent the number of buffer gets required to satisfy a particular query.

Now, 'db block gets'. A 'db block get' is a copy of the 'current mode block'. That is, the data in the block, as it exists currently, or at this point in time. Note that while multiple CR copies of a block may exist in the buffer cache, there can only ever be one current mode copy of a block in the buffer cache at any one time. (RAC is a special case, w/ shared current and exclusive current, but I'm not going to get into that here.) So, a 'db block get' is a buffer get in current mode. 'db block gets' are usually associated w/ DML, and in that scenario, will implicitly lock one or more rows in that block. Also, there is a notable case where db block gets can occur with a select statement. That will happen when you're doing a FULL TABLE SCAN on a table or a FAST FULL SCAN on an index. In those cases, the segment header is read (usually multiple times for some unknown reason) in current mode.

Next, 'physical reads': A physical read will occur any time a consistent get or a db block get goes looking for block and can't find it in the buffer cache. So, for each block read from disk, physical reads will be incremented. Gets which result in physical reads are counted both as as get and as a read in the statistics. So, if you do 10 consistent gets and 5 of them require physical reads, you should see consistent gets incremented by 10 and physical reads incremented by 5.

Now, what's up w/ arraysize? Well, arraysize is the client side setting for SQL*Plus specifying the size of the array that will receive result sets. The default, as you learned, is 15. Now, suppose you have a table where there are 30 records per block, and 3,000 rows in the table. But, your arraysize is 15. So, your server process will get the first 15 rows, and return them from the first block buffer. Now, for the next 15, you need to get that same block again, for rows 16-30. So, you need to do two buffer gets per block to get all the rows. For a 3,000 row table, you'll do (approximately) 3,000/15 = 200 buffer gets. If you change your arraysize to 30, you can get away w/ visitng each block only once and do 3,000/30 = 100 buffer gets.

So, consider that even after you've optimized a particular SQL statement, if the arraysize is too small, you're going to force your server process to do excess database calls (FETCH calls), and extra buffer gets as well. This can best be illustrated with a test similar to what you did, but try looking at the raw trace file for FETCH calls. The number of FETCH calls ought to be very close to (number of rows returned / arraysize). The 'r=xxx' in the FETCH call data in the trace file is the number of rows returned, which is probably what your arraysize is set to.

So, db block gets, consistent gets, and physical reads are all measured in buffers (or blocks). If the same block is requested multiple times, it will be counted that many times in these statistics. Oracle will always access data from the buffer cache by the buffer. All 'get' operations are by the buffer, never by row. After the buffer is 'gotten', Oracle parses the block to get the data for the relevant rows.


When a "consistent get" is done, this doesn't necessarily mean that Oracle had to do any rollback/undo of DML in order to get the consistent image. Rather, it just means that Oracle requested a copy of the block as of the point in time that the query was started (a "consistent snapshot"). So, I believe it is quite normal to have many, many consistent gets even if there is NO DML occuring.


自己做的一個更詳細的測試:
用到的查詢統計信息的語句;
select sid,value,name from v$sesstat x,v$statname y
where x.statistic#=y.statistic#
and ( name like '%db block%gets%' or name like '%consistent%gets%'
or name like '%consistent%change%' or name like '%db block%change%'
or name like '%physical writes%' or name like '%physical reads%'
or name = 'index fetch by key' or name like '%read%' or name like '%scans%'  
)
and sid = 11 and value > 0
order by value

Scott用戶登錄,但是沒有做任何操作,sid爲10,在另外一個用戶下查詢:
   SID    VALUE NAME
---------- ---------- --------------------------------
       11       3 db block gets
       11       0 physical reads
       11       4 db block changes
       11       0 consistent changes
       11       0 physical writes
       11       0 physical writes non checkpoint
       11       0 physical reads direct
       11       0 physical writes direct
       11       0 physical reads direct (lob)
       11       0 physical writes direct (lob)

在scott sid=11下運行select * from emp後,結果沒有任何變化,這是不應該的,應該有physical reads與db block gets的值變化

在scott sid = 11下運行update emp set comm = 10; 在另外一個用戶下查詢:
   SID    VALUE NAME
--------- ---------- ------------------------------
   11       18 db block gets
   11       0 physical reads
   11       33 db block changes
   11       0 consistent changes
   11       0 physical writes
   11       0 physical writes non checkpoint
   11       0 physical reads direct
   11       0 physical writes direct
   11       0 physical reads direct (lob)
   11       0 physical writes direct (lob)

再次在scott sid = 11的同一個session下運行update emp set comm = 10; 在另外一個用戶下查詢:
SID    VALUE NAME
------- ---------- -------------------------------
    11       32 db block gets
    11       0 physical reads
    11       61 db block changes
    11       0 consistent changes
    11       0 physical writes
    11       0 physical writes non checkpoint
    11       0 physical reads direct
    11       0 physical writes direct
    11       0 physical reads direct (lob)
    11       0 physical writes direct (lob)
不要commit;

用scott再次登錄, sid 爲17,在另外一個用戶下查詢:
SID    VALUE NAME
------- ---------- --------------------------------
    17       3 db block gets
    17       0 physical reads
    17       4 db block changes
    17       0 consistent changes
    17       0 physical writes
    17       0 physical writes non checkpoint
    17       0 physical reads direct
    17       0 physical writes direct
    17       0 physical reads direct (lob)
    17       0 physical writes direct (lob)

在scott session 17,下運行select * from emp 後,在另外一個用戶下查詢:
    SID    VALUE NAME
-------- ---------- --------------------------------
   17       3 db block gets
   17       0 physical reads
   17       5 db block changes
   17       28 consistent changes
   17       0 physical writes
   17       0 physical writes non checkpoint
   17       0 physical reads direct
   17       0 physical writes direct
   17       0 physical reads direct (lob)
   17       0 physical writes direct (lob)

再次在scott session 17,下運行select * from emp 後,在另外一個用戶下查詢:
   SID    VALUE NAME
----- ---------- ---------------------------------
17       3 db block gets
17       0 physical reads
17       6 db block changes
17       56 consistent changes
17       0 physical writes
17       0 physical writes non checkpoint
17       0 physical reads direct
17       0 physical writes direct
17       0 physical reads direct (lob)
17       0 physical writes direct (lob)

在此在scott sid = 11的同一個session下運行rollback; 在另外一個用戶下查詢:
SID    VALUE NAME
------ ---------- ------------------------------
11       89 db block gets
11       0 physical reads
11        118 db block changes
11       0 consistent changes
11       0 physical writes
11       0 physical writes non checkpoint
11       0 physical reads direct
11       0 physical writes direct
11       0 physical reads direct (lob)
11       0 physical writes direct (lob)

再次在scott sid = 11的同一個session下運行update emp set comm = 10; 在另外一個用戶下查詢:
SID    VALUE NAME
---- ---------- --------------------------------
   11        104 db block gets
   11       0 physical reads
   11        147 db block changes
   11       0 consistent changes
   11       0 physical writes
   11       0 physical writes non checkpoint
   11       0 physical reads direct
   11       0 physical writes direct
   11       0 physical reads direct (lob)
   11       0 physical writes direct (lob)

再次在scott sid = 11的同一個session下運行commit; 在另外一個用戶下查詢:
SID    VALUE NAME
---- ---------- ------------------------------
   11        105 db block gets
   11       0 physical reads
   11        148 db block changes
   11       0 consistent changes
   11       0 physical writes
   11       0 physical writes non checkpoint
   11       0 physical reads direct
   11       0 physical writes direct
   11       0 physical reads direct (lob)
   11       0 physical writes direct (lob)

經過初步試驗,發現如果開始運行select * from emp後,然後再運行select * from emp where empno = 7902, 不管運行多少此,都不會引起physical reads與db block gets的增加。因爲db block gets是在current mode模式中產生的。
而是隻會引起session logical reads與index fetch by key、consistent gets的增加。
如運行
select sid,value,name from v$sesstat x,v$statname y
where x.statistic#=y.statistic#
and ( name like '%db block%change%' or name like '%db block%get%'
or name like '%consistent%change%' or name like '%physical reads%'
or name like '%physical writes%' or name like '%scans%'
or name = 'index fetch by key' or name like '%read%'
)
and sid = 11 and value > 0
order by value
查詢後,得到:
SID    VALUE NAME
---- ---------- -------------------------------
   11       3 db block gets
   11       4 db block changes
   11       4 index scans kdiixs1
   11       5 index fetch by key
   11       6 table scans (short tables)
   11       8 no work - consistent read gets
   11       42 session logical reads

將數據庫關閉,重新啓動後,重新用scott聯接,sid = 12立即查詢統計信息,得到:
SID    VALUE NAME
---- ---------- -------------------------------
   12       6 db block gets
   12       6 table scans (short tables)
   12       8 db block changes
   12       53 cluster key scans
   12       89 index fetch by key
   12        145 physical reads
   12        163 index scans kdiixs1
   12        337 consistent gets - examination
   12        423 no work - consistent read gets
   12        945 consistent gets
   12        951 session logical reads

在sid =12 session中運行select * from emp where empno = 7902;後,得到統計信息:
SID    VALUE NAME
---- ---------- -------------------------------
   12       6 db block gets
   12       6 table scans (short tables)
   12       8 db block changes
   12       60 cluster key scans
   12       98 index fetch by key
   12        150 physical reads
   12        168 index scans kdiixs1
   12        360 consistent gets - examination
   12        439 no work - consistent read gets
   12        990 consistent gets
   12        996 session logical reads
再次運行select * from emp;則db block gets與physical reads不發生變化

將數據庫關閉,重新啓動後,重新用scott聯接,sid = 12立即查詢統計信息,得到:
SID    VALUE NAME
---- ---------- --------------------------------
   12       6 db block gets
   12       6 table scans (short tables)
   12       8 db block changes
   12       53 cluster key scans
   12       89 index fetch by key
   12        145 physical reads
   12        163 index scans kdiixs1
   12        337 consistent gets - examination
   12        423 no work - consistent read gets
   12        945 consistent gets
   12        951 session logical reads

在sid =12 session中運行select * from emp;後,得到統計信息:
SID    VALUE NAME
--- ---------- -------------------------------
12       6 db block gets
12       7 table scans (short tables)
12       8 db block changes
12       60 cluster key scans
12       97 index fetch by key
12        149 physical reads
12        168 index scans kdiixs1
12        358 consistent gets - examination
12        441 no work - consistent read gets
12        992 consistent gets
12        998 session logical reads
再次運行select * from emp;則db block gets與physical reads不發生變化
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章