SQL Monitor details for later tuning. 29 March 2012Posted by David Alejo Marcos in Exadata, Oracle 11.2, RAC, SQL - PL/SQL, Tuning.
Tags: Exadata, Oracle 11.2, RAC, SQL, SQL - PL/SQL, Tuning
Tuning has always being good fun and something like a challenge for me.
From time to time we are being asked to find out why something did run slow while you are sleeping; answering this question is, in most cases, a challenge.
My batch did run slow last night, can you let us know why? Or why did this query run slow? Are questions we, as DBAs, have to answer from time to time.
Oracle has provided us with many tools to dig out information about past operations. We have EM, AWR, ASH, dba_hist_* tables, scripts all over internet, etc.
I must admit I do use sql_monitor quite often, but on a really busy environment, Oracle will only keep, with any luck, couple of hours of SQLs.
V$SQL_MONITOR and dbms_sqltune.report_sql_monitor have become tools I use most frequently.
The only problem I have is, as mentioned earlier, the number of SQLs stored on v$sql_monitor or, rather, the length of time being kept there.
Oracle will keep a certain number of SQLs (defined by a hidden parameter) and start recycling them so, by the time I am in the office, any SQL executed during the batch is long gone.
For this reason I came up with the following. I must admit it is not rocket science, but it does help me quite a lot.
It is like my small collection of “Bad Running Queries”. And I only need another DBA or an operator with certain privileges to execute a simple procedure to allow me to try to find out what did happen.
We need the following objects:
1.- A table to store the data:
CREATE TABLE perflog ( asof DATE, userid VARCHAR2(30), sql_id VARCHAR2 (30), monitor_list CLOB, monitor CLOB, monitor_detail CLOB ); /
2.- A procedure to insert the data I need for tuning:
CREATE OR REPLACE PROCEDURE perflog_pr (p_sql_id VARCHAR2 DEFAULT 'N/A') AS BEGIN IF p_sql_id = 'N/A' THEN INSERT INTO perflog SELECT SYSDATE, sys_context('USERENV', 'SESSION_USER'), p_sql_id, sys.DBMS_SQLTUNE.report_sql_monitor_list (TYPE => 'HTML', report_level => 'ALL'), NULL, NULL FROM DUAL; ELSE INSERT INTO perflog SELECT SYSDATE, sys_context('USERENV', 'SESSION_USER'), p_sql_id, sys.DBMS_SQLTUNE.report_sql_monitor_list (TYPE => 'HTML', report_level => 'ALL'), sys.DBMS_SQLTUNE.report_sql_monitor (sql_id => p_sql_id, TYPE => 'ACTIVE', report_level => 'ALL'), sys.DBMS_SQLTUNE.report_sql_detail (sql_id => p_sql_id, TYPE => 'ACTIVE', report_level => 'ALL') FROM DUAL; END IF; COMMIT; END; /
3.- Grant necessary permissions:
grant select, insert on perflog to public / create public synonym perflog for perflog / grant execute on perflog_pr to public / create public synonym perflog_pr for perflog_pr / grant select any table, select any dictionary to <owner_code> /
The way it works is as follows:
- If business complains regarding a specific query, the DBA or operator can call the procedure with the sql_id:
exec perflog_pr ('1f52b50sq59q');
This will store the datetime, sql_id, DBA/operator name and most important the status of the instance at that time, general view of the sql and a detailed view of the sql running slow.
- If business complains regarding slowness but does not provide a specific query, we execute the following:
This will store the datetime, sql_id, DBA/operator name and a general view of the instance.
Please, give it a go and let me know any thoughts.
As always, comments are welcome.
David Marcos Consulting Ltd.