在ORACLE數據庫應用調優中,一個SQL的執行次數/頻率也是常常需要關注的,因為某個SQL執行太頻繁,要麼是由於應用設計有缺陷,需要在業務邏輯上做出優化處理,要麼是業務特殊性所導致。如果執行頻繁的SQL,往往容易遭遇一些並發性的問題。
那麼如何查看ORACLE數據庫某個SQL的執行頻率/次數呢? 有哪些途徑方法呢?
方法1: 通過查詢V$SQLAREA或V$SQL的EXECUTIONS來查看SQL的執行次數,但是這個值的有效性需要結合FIRST_LOAD_TIME來判斷。因為V$SQLAREA或V$SQL中不保存歷史數據,具有一定的時效性,所以如果要查詢很久以前的某個SQL執行次數是辦不到的。
關於V$SQLAREA
FIRST_LOAD_TIME VARCHAR2(19) Timestamp of the parent creation time
EXECUTIONS NUMBER Total number of executions, totalled over all the child cursors
如下所示,我們通過一個例子來演示如何查詢一個語句的執行次數。
SQL> COL START_TIME FOR A20;
SQL> SELECT TO_CHAR(sysdate,'YYYY-MM-DD HH24:MI:SS') AS START_TIME FROM DUAL;
START_TIME
--------------------
2014-11-20 13:51:21
SQL>
SQL> SELECT SQL_ID, SQL_TEXT,FIRST_LOAD_TIME, EXECUTIONS
2 FROM V$SQLAREA
3 WHERE SQL_TEXT LIKE '%SELECT * FROM TEST%';
SQL_ID SQL_TEXT RST_LOAD_TIME EXECUTIONS
----------- -------------------------------------- ---------------- ----------
SQL> SELECT * FROM TEST;
ID NAME
----------- ----------
SQL>
SQL> SELECT SQL_ID, SQL_TEXT,FIRST_LOAD_TIME, EXECUTIONS
2 FROM V$SQLAREA
3 WHERE SQL_TEXT LIKE '%SELECT * FROM TEST%';
SQL_ID SQL_TEXT FIRST_LOAD_TIME EXECUTIONS
----------- -------------------------------------- ---------------- --------------
4ntr8ag38ujwd SELECT * FROM TEST 2014-11-20/13:51:40 1
SQL> SELECT * FROM TEST;
ID NAME
----------- ----------
SQL>
SQL> SELECT SQL_ID, SQL_TEXT,FIRST_LOAD_TIME, EXECUTIONS
2 FROM V$SQLAREA
3 WHERE SQL_TEXT LIKE '%SELECT * FROM TEST%';
SQL_ID SQL_TEXT FIRST_LOAD_TIME EXECUTIONS
------------- -------------------------------- ------------------- ----------
4ntr8ag38ujwd SELECT * FROM TEST 2014-11-20/13:51:40 2
如果此時清空共享池,那麼你會發現V$SQLAREA中對應的SQL的EXECUTIONS次數清零了。
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
System altered
SQL> SELECT * FROM TEST;
ID NAME
----------- ----------
SQL>
SQL> SELECT SQL_ID, SQL_TEXT,FIRST_LOAD_TIME, EXECUTIONS
2 FROM V$SQLAREA
3 WHERE SQL_TEXT LIKE '%SELECT * FROM TEST%';
SQL_ID SQL_TEXT FIRST_LOAD_TIME EXECUTIONS
------------- ----------------------------------- ------------------- ----------
4ntr8ag38ujwd SELECT * FROM TEST 2014-11-20/13:52:38 1
SQL>
如果要查看某個時間段該SQL語句執行了多少次,那麼必須在這兩個時間段執行上面SQL語句,兩次EXECUTIONS的差值表示這段時間內SQL語句的執行次數。EXECUTIONS是全局的,往往不能查看某個會話或用戶執行了多少次。這也是其局限性之一。
方法2:通過DBA_HIST_SQLSTAT關聯DBA_HIST_SNAPSHOT找出某些SQL的執行次數,但是部分快照如果沒有捕獲到有些SQL。這樣也就無法通過下面SQL語句查看執行次數。也是就說這種方法是有缺陷的。執行越頻繁的語句,也越容易被SNAPSHOT抓取到.
SELECT M.SQL_ID ,
TO_CHAR(N.BEGIN_INTERVAL_TIME, 'YYYY-MM-DD') "DATETIME",
SUM(M.EXECUTIONS_DELTA) EXECUTIONS
FROM DBA_HIST_SQLSTAT M, DBA_HIST_SNAPSHOT N
WHERE M.SNAP_ID = N.SNAP_ID
AND M.DBID = N.DBID
AND M.INSTANCE_NUMBER = N.INSTANCE_NUMBER
AND M.INSTANCE_NUMBER=1
AND TO_CHAR(N.BEGIN_INTERVAL_TIME, 'YYYY-MM-DD') ='2014-11-20'
AND M.SQL_ID=&SQL_ID
GROUP BY M.SQL_ID , TO_CHAR(N.BEGIN_INTERVAL_TIME, 'YYYY-MM-DD')
ORDER BY M.SQL_ID
方法3:AWR報告查看某個SQL的執行次數,同上面一樣,AWR報告也受SNAPSHOT影響。不一定捕獲了你需要查詢的SQL
查看當前數據庫執行次數最多的SQL,例如,查詢執行最頻繁的TOP 15的SQL語句。
SELECT SQL_TEXT, EXECUTIONS
FROM (SELECT SQL_TEXT,
EXECUTIONS,
RANK() OVER(ORDER BY EXECUTIONS DESC) EXEC_RANK
FROM V$SQLAREA)
WHERE EXEC_RANK <= 15;
參考資料:
http://www.itpub.net/thread-1320984-1-1.html