Oracle 11g direct path read 等待事件的理解
在Oracle 11g中,全表掃描可能使用direct path read方式,繞過buffer cache,這樣的全表掃描就是物理讀了。 在10g中,都是通過gc buffer來讀的,所以不存在direct path read的問題。
direct path read較高的可能原因有:
1. 大量的磁碟排序操作,order by, group by, union, distinct, rollup, 無法在PGA中完成排序,需要利用temp表空間進行排序。 當從臨時表空間中讀取排序結果時,會產生direct path read.
2. 大量的Hash Join操作,利用temp表空間儲存hash區。
3. SQL語句的並行處理
4. 大表的全表掃描,在中,全表掃描的演算法有新的變化,根據表的大小、快取記憶體的大小等資訊,決定是否繞過SGA直接從磁碟讀Oracle11g取資料。而10g則是全部通過快取記憶體讀取資料,稱為table scan(large)。11g認為大表全表時使用直接路徑讀,可能比10g中的資料檔案雜湊讀(db file scattered reads)速度更快,使用的latch也更少。
大量的direct path read等待時間最可能是一個應用程式問題。 direct path read事件由SQL語句驅動,這些SQL語句執行來自臨時的或常規的表空間的直接讀取操作。 當輸入的內容大於PGA中的工作區域時,帶有需要排序的函式的SQL語句將排序結果寫入到臨時表空間中,臨時表空間中的排序順序串隨後被合併,用於提供最終的結果。讀取排序結果時,Oracle會話在direct path read等待事件上等待。DB_FILE_DIRECT_IO_COUNT初始化引數可能影響direct path read的效能。
一個隱含引數:
_serial_direct_read = false 禁用direct path read
_serial_direct_read = true 啟用direct path read
alter sytem set "_serial_direct_read"=never scope=both sid='*'; 可以顯著減少 direct path read
本案例:由於沒有走索引,導致全表掃描,資料庫event狀態是direct path read
-- 檢視sql session 執行情況
SELECT S.SID,S.LAST_CALL_ET, (SELECT ST.VALUE FROM V$SESSTAT ST WHERE ST.SID = S.SID AND ST.STATISTIC# = TO_NUMBER('38') ) CRITERIA_VALUE, S.BLOCKING_SESSION,S.BLOCKING_INSTANCE,S.BLOCKING_SESSION_STATUS, (SELECT CASE WHEN NOT S.BLOCKING_SESSION IS NULL THEN 'kill -9 '|| GP.SPID ELSE NULL END FROM GV$PROCESS GP,GV$SESSION GS WHERE GS.PADDR = GP.ADDR AND GS.SID=S.BLOCKING_SESSION AND GS.INST_ID=GP.INST_ID ) KILL_BLOCK_PROC, (SELECT CASE WHEN NOT S.BLOCKING_SESSION IS NULL THEN 'ALTER SYSTEM KILL SESSION '''|| GS.SID || ',' || GS.SERIAL# ||''' IMMEDIATE;' ELSE NULL END FROM GV$SESSION GS WHERE GS.SID=S.BLOCKING_SESSION AND GS.SID=S.BLOCKING_SESSION AND GS.INST_ID=S.BLOCKING_INSTANCE ) KILL_BLOCK_SESSION, S.CLIENT_IDENTIFIER,S.SERVER,S.USERNAME,S.MACHINE,S.PROGRAM,S.MODULE,S.ACTION, (SELECT AC.NAME FROM ( SELECT ACTION, NAME FROM AUDIT_ACTIONS UNION SELECT 189, 'MERGE' FROM DUAL ) AC WHERE AC.ACTION = S.COMMAND + CASE WHEN S.COMMAND < 0 THEN 256 ELSE 0 END) COMMAND, S.STATUS,S.LOCKWAIT,S.EVENT,S.STATE,S.WAIT_CLASS,S.WAIT_CLASS#,S.WAIT_TIME,T.EXECUTIONS,T.OPTIMIZER_MODE,T.OPTIMIZER_COST,T.CPU_TIME,T.DISK_READS,T.BUFFER_GETS,T.SORTS,T.SHARABLE_MEM, T.PERSISTENT_MEM,T.RUNTIME_MEM,T.ROWS_PROCESSED,T.COMMAND_TYPE,O.OBJECT_ID,O.OBJECT_NAME,F.FILE_ID,F.FILE_NAME,F.TABLESPACE_NAME, S.ROW_WAIT_BLOCK#,S.ROW_WAIT_ROW#,S.LOGON_TIME,T.SQL_TEXT,T.SQL_FULLTEXT, 'SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('''||T.SQL_ID||''','||T.CHILD_NUMBER||'));' PLAN, 'ALTER SYSTEM KILL SESSION ''' || S.SID || ',' || S.SERIAL# || ''' POST_TRANSACTION IMMEDIATE;' KILL_SESSION, 'SELECT SQL_TEXT,SQL_FULLTEXT,LAST_ACTIVE_TIME,DBMS_SQLTUNE.EXTRACT_BINDS(BIND_DATA) BIND FROM V$SQL WHERE SQL_ID='''||S.SQL_ID||''' ORDER BY LAST_ACTIVE_TIME DESC;' BIND FROM V$SESSION S,V$SQL T,DBA_OBJECTS O,DBA_DATA_FILES F WHERE S.SQL_HASH_VALUE = T.HASH_VALUE AND S.STATUS = 'ACTIVE' AND F.FILE_ID=ROW_WAIT_FILE# AND S.ROW_WAIT_OBJ#=O.OBJECT_ID ORDER BY LAST_CALL_ET DESC;