數據庫SQL的監控和優化的核心,其實主要在於「行讀」! 監控找出行讀高的SQL,而優化的最直接手段就是下降行讀數。
oracle的監控方法和監控工具可能有千百種,這裏介紹我經常使用的幾種簡單而直接的方式:sql
注意:如下監控SQL須要用戶有oracle的管理視圖查詢權限。 數據庫
假如你的oracle此時響應速度較慢,從服務器的TOP能夠看到oracle進程佔用了較多CPU,或者有較多的iowait,那麼能夠直接用下面的SQL語句來查詢正在執行的較耗資源的SQL。服務器
SELECT A.,B.SQLTEXT FROM (SELECT z.SPID AS 操做系統PID ,x.SID , x.SERIAL# , x.USERNAME , x.SQLID FROM v$session x , v$process z WHERE x.PADDR = z.ADDR AND Z.SPID = '10341')A LEFT JOIN v$sql B ON A.SQLID = B.SQLID;
恭喜你,你可能已經直接找到有問題的SQL了。session
若是不知道pid,那稍微改動下上面的SQL,能夠直接查當前oracle庫正在執行的全部SQL,按照時間倒序排序,同樣能抓到最可疑的SQL。oracle
SELECT z.SPID AS 操做系統PID ,x.SID , x.SERIAL# , x.USERNAME , x.LOCKWAIT , x.STATUS , x.SCHEMANAME , x.OSUSER , x.PROCESS , x.MACHINE , x.PORT , x.PROGRAM , x.SQL_ID , x.SQL_CHILD_NUMBER , x.SQL_EXEC_START , x.PREV_SQL_ID , CASE x.ROW_WAIT_OBJ# WHEN - 1 THEN NULL ELSE (dbms_rowid.rowid_create (1, ROW_WAIT_OBJ#, ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW#)) END AS rowinfo , x.LAST_CALL_ET , x.BLOCKING_SESSION_STATUS , x.BLOCKING_SESSION , x.FINAL_BLOCKING_SESSION_STATUS , x.FINAL_BLOCKING_SESSION , x.EVENT , x.WAIT_CLASS , x.STATE , x.WAIT_TIME_MICRO , y.SQL_TEXT , y.EXECUTIONS , CASE EXECUTIONS WHEN 0 THEN y.BUFFER_GETS ELSE y.BUFFER_GETS / EXECUTIONS END AS AVG_BUFFER_GETS , CASE EXECUTIONS WHEN 0 THEN y.DISK_READS ELSE y.DISK_READS / EXECUTIONS END AS AVG_DISK_READS , y.ELAPSED_TIME / 1000000 AS AVG_ELAPSED_TIME , y.CPU_TIME / 1000000 AS AVG_CPU_TIME FROM v$session x , v$process z , v$sql y WHERE x.PADDR = z.ADDR AND x.SQL_ID = y.SQL_ID --AND Z.SPID = 'XXXX' --AND x.USERNAME='DEV' AND x.STATUS = 'ACTIVE' ORDER BY x.WAIT_TIME_MICRO desc;
若是是要查剛剛(由v$sqlarea存活時間而定)執行過的SQL中,哪些是比較耗資源的,能夠試試下面這個:ide
SELECT * FROM (SELECT EXECUTIONS , BUFFER_GETS / EXECUTIONS AS AVG_BUFFER_GETS , DISK_READS / EXECUTIONS AS AVG_DISK_READS , ELAPSED_TIME / (EXECUTIONS*1000000) AS AVG_ELAPSED_TIME , CPU_TIME / (EXECUTIONS*1000000) AS AVG_CPU_TIME , SQL_TEXT , SQL_ID , SORTS / EXECUTIONS AS AVG_SORTS , SHARABLE_MEM , APPLICATION_WAIT_TIME / EXECUTIONS AS AVG_APPLICATION_WAIT_TIME , CONCURRENCY_WAIT_TIME / EXECUTIONS AS AVG_CONCURRENCY_WAIT_TIME , USER_IO_WAIT_TIME / EXECUTIONS AS AVG_USER_IO_WAIT_TIME , ROWS_PROCESSED FROM v$sqlarea WHERE EXECUTIONS > 0 AND PARSING_SCHEMA_NAME<>'SYS' AND LAST_ACTIVE_TIME BETWEEN to_date('2016-04-25 08:00:00','yyyy-mm-dd hh24:mi:ss') AND to_date('2017-07-25 12:00:00','yyyy-mm-dd hh24:mi:ss') ORDER BY AVG_ELAPSED_TIME DESC) x WHERE ROWNUM < 100;
修改ORDER BY AVG_ELAPSED_TIME DESC 爲其餘字段,好比 AVG_BUFFER_GETS就能查出哪些SQL的緩衝池讀比較高。工具
注意:v$sqlarea是在內存中的,此SQL的查詢時間範圍無法過久遠。優化
若是是要查最近7天內執行過的SQL中,哪些是比較耗資源的,那咱們能夠改用dba_hist_sqlstat進行查詢,它默認是存儲7/8天的。不過須要預先知道dbid、instance_number、snap_id這幾個數據,熟悉oracle的朋友應該清楚,awr報告的數據正是來源於此。操作系統
SELECT y.*,round(y.elap/y.exec,2) AS AVG_ELAP,z.SQL_TEXT FROM (SELECT x.sql_id , max (module) module , sum (elapsed_time_delta)/ 1000000 elap , sum (cpu_time_delta) cput , sum (executions_delta) exec FROM dba_hist_sqlstat x WHERE x.dbid = 901548675 AND x.instance_number = 1 AND 5604 < x.snap_id AND x.snap_id <= 5612 AND x.MODULE = 'JDBC Thin Client' GROUP BY x.sql_id)y LEFT JOIN dba_hist_sqltext z ON y.sql_id = z.sql_id WHERE y.exec >0 ORDER BY y.elap/y.exec DESC
若是以上4種方式還不足以解君之憂的話,那麼仍是來份AWR報告吧。code
固然AWR報告也不是萬能的,好比報告中TOP SQL的排序是按照總資源消耗倒序排序的,假設某些SQL執行次數不多可是單次消耗資源不少的,那可能會被掩蓋掉而沒有在報告中展現出來。
至於AWR報告如何生成如何解讀,本篇再也不贅述。
以上介紹了幾種非專業DBA快速定位oracle TOP SQL的方式,但願於君有益。