非空閒的等待事件-db file scattered read

蘭在晨發表於2015-12-09

db file scattered read

(USER I/0類)與事件db file sequential read相類似。

  1. 當會話釋出一個讀入多個資料塊的IO請求時提交該事件。ORACLE會話等待多個連續的資料塊(由初始引數DB_FILE_MULTIBLOCK_READ_COUNT指定)從磁碟讀入到SGA中。
  2. 該事件是在全表掃描或索引快速全域性掃描時發生的典型事件。
  3. 初始化引數db_file_multiblock_read_count(MBRC)決定了讀取資料塊的最大數目,有兩種情況會造成多塊讀取操作被分成幾次操作:

>> MBRC因子不能跨越整個區,如果一個區包含10個塊,MBRC因子=8,那麼多塊讀取會發布兩次讀取呼叫,一次8個資料塊,一次2個資料塊。

>> 要讀取的多塊有,有一部分已在CACHE中,這時多塊讀取操作被分化成幾次來完成。

  1. 有時在db file scattered read事件中會夾雜db file sequential read事件,出現的原因是:

>> 區邊界:當某個區中的最後一組塊只有一個塊時,ORALCE使用單塊讀取呼叫取出這個塊。這通常不是一個問題,除非區尺寸過小。

>> 存在較多的連結的或遷移的行。ORALCE使用單塊I/O呼叫尋求每個連結的或遷移的行。在DBA_TABLES檢視中檢查表的CHAIN_CNT,如果該值較大,需要重新組織表(匯入/匯出或alter table move)。

>> 索引條目的建立。如在使用insert into table_A select * from table_B,如果table_A上有一個索引,在執行該語句時,會產生很多db sequential read事件,這是將索引塊讀入SGA中的結果。

[@more@]
  1. MBRC因子的合理設定方法:

alter session set db_file_multiblock_read_count=1000; -- 設定一個高得離譜的MBRC因子

select /*+ full(a) */ count(*) from big_table a; -- 進行全域性掃描

結果:通過捕獲10046事件,從生成的Trace檔案中獲得的P3的值就是最佳MBRC因子,以下是針對計程車系統,看來最佳的MBRC因子是64。

WAIT #1: nam='db file scattered read' ela= 48518 p1=12 p2=10 p3=64

WAIT #1: nam='db file scattered read' ela= 42922 p1=12 p2=74 p3=64

WAIT #1: nam='db file scattered read' ela= 41369 p1=12 p2=138 p3=64

WAIT #1: nam='db file scattered read' ela= 42752 p1=12 p2=202 p3=64

  1. 存在該事件並不一定表示存在效能問題,但是如果該事件的等待時間比其他等待時間多得多,則必須調查其原因。當SQL語句訪問物件中的大多數行時,使用db file scattered read很有用處。
  2. 當確定了引起該事件劇增的SQL語句後,就檢查該SQL語句的執行計劃。

>> 該語句是否應該通過全表掃描或索引FFS訪問資料?

>> 索引掃描或唯一掃描是否更為有效?

>> 查詢是否使用了正確的驅動表?

>> SQL謂詞是否適合於雜湊或合併聯接?

>> 如果全表掃描是合適的,並行查詢是否可以改進響應時間?

  1. 如果執行良好的應用程式突然在此事件中花費了大量時間,並且沒有任何程式碼改變,可能需要檢視是否一個或多個索引已經被刪除或不可用。
  2. 如果資料庫物件的統計資訊不精確,如:統計資訊表明該表只有幾行,而實際上有上百成行,也會造成優化器選擇全表掃描訪問路徑,這時要使用EXEC SYS.DBMS_STATS.gather_table_stats('RECKON','RCNT_INCOME',estimate_percent => 10)或analyze table RCNT_INCOME estimate STATISTICS來重新整理統計。

在ORACLE10g中,表監控預設是啟動的。

  1. 有些初始化引數的值可以導致優化器轉向全域性掃描,如:DB_FILE_MULTIBLOCK_READ_COUNT(MBRC),HASH_AREA_SIZE、OPTIMIZER_INDEX_COST_ADJ。
  2. v$sesstat檢視也有當前會話的全表掃描統計資訊,但沒有時間元素,所以v$session_event是更好的檢視。

>> 以v$sesstat檢視作為查詢物件的示例:

select a.SID, b.name, a.VALUE
from v$sesstat a, v$statname b
where a.STATISTIC# = b.STATISTIC#
and a.VALUE <> 0
and b.NAME = 'table scan blocks gotten'

注:以此查詢可以粗略知道系統中大約什麼會話出現很多的表掃描。

>> 以v$session_event為基礎的查詢:

select a.sid,
a.event,
a.time_waited,
round(a.time_waited/c.sum_time_waited*100 , 2) || '%' pct_wait_time,
round((sysdate - b.LOGON_TIME) * 24) hours_connected
from v$session_event a,
v$session b,
(select sid, sum(time_waited) sum_time_waited
from v$session_event

where event not in ('null event', 'SQL*Net message to client',
'pmon timer', 'pipe get', 'smon timer', 'jobq slave wait',
'rdbms ipc message', 'rdbms ipc reply', 'PX Deq: Join ACK',
'PX Deq: Signal ACK')
having sum(time_waited) > 0 -- 對group by 產生結果的挑選
group by sid) c
where a.sid = b.sid
and a.sid = c.sid
and a.TIME_WAITED > 0
and a.EVENT = 'db file scattered read'
order by hours_connected desc, pct_wait_time

  1. 查詢當前執行全域性掃描的SQL語句,v$sql_plan中是否包含該事件:

select hash_value,
child_number,
lpad(' ', 2 * depth) || operation || ' ' || options ||
decode(id, 0, substr(optimizer, 1, 6) || ' Cost=' || to_char(cost)) operation,
object_name object,
cost,
cardinality,
round(bytes / 1024) kbytes
from v$sql_plan
where hash_value in
(select a.sql_hash_value
from v$session a, v$session_wait b
where a.sid = b.sid
and b.event = 'db file scattered read')
order by hash_value, child_number, id

  1. 引數說明:

事件號:188

事件名:db file scattered read

引數一:讀取塊的檔案號碼file#

引數二:起始塊號block#

引數三:讀取的塊總數blocks

由引數P1與P2推得訪問的資料物件:

select s.segment_name, s.partition_name
from dba_extents s
where <P2的值> between s.block_id and (s.block_id + s.blocks -1) and s.file_id = <P1的值>

  1. 等待時間:無超時

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

相關文章