Performance Tuning and SQL Monitoring Scripts | Oracle DBA Scripts All in One -4

Hi,

I will share all Oracle DBA Scripts ( Oracle RAC, Dataguard, Performance Tuning, Monitoring and etc.. ) in this tutorial series.

 

 

SQL Performance Tuning Scripts

Oracle DBA ( Database Administrator ) needs useful scripts to monitor, analyze and check Oracle database for routine database operations and monitoring.

 

 

Before Oracle DBA Scripts, If you don’t know Oracle database and want to learn, click following link to start learning Oracle database with this tutorial.

Oracle Tutorial | Oracle Database Tutorials for Beginners ( Junior Oracle DBA )

 

 

 

 

SQL Monitoring Scripts in Oracle

Oracle DBA should monitor database everytime and if there are many sqls which is running long execution time then it should be reported to the developer and developer and dba should examine these sqls.

You can find TOP Elapsed time SQL in certain hours with below script.

 

SELECT st.sql_text, sub.sql_id, sub.ELAPSED_TIME PER_EXEC_ELAPSED_TIME_MINUTES
FROM DBA_HIST_SQLTEXT st,
( SELECT t.sql_id,
ROUND (
SUM (t.elapsed_time_delta / 60000000)
/ SUM (t.executions_delta))
ELAPSED_TIME
FROM dba_hist_sqlstat t, dba_hist_snapshot s, DBA_HIST_SQLTEXT st
WHERE t.snap_id = s.snap_id
AND t.dbid = s.dbid
AND t.instance_number = s.instance_number
AND t.executions_delta > 0
AND s.BEGIN_INTERVAL_TIME >
TO_DATE ('11/15/2018 13:00:00',
'mm/dd/yyyy hh24:mi:ss')
AND END_INTERVAL_TIME <
TO_DATE ('11/15/2018 16:01:00',
'mm/dd/yyyy hh24:mi:ss')
GROUP BY t.sql_id
ORDER BY 2 DESC) sub
WHERE sub.sql_id = st.sql_id
ORDER BY 3 DESC;



TOP CPU SQL Statements

You can find TOP CPU SQL for last 24 hours with following script.

 

select * from (
select ss.sql_text,
    a.SQL_ID, 
    sum(CPU_TIME_DELTA), 
    sum(DISK_READS_DELTA),
    count(*)
from 
    DBA_HIST_SQLSTAT a, dba_hist_snapshot s,v$sql ss
where
 s.snap_id = a.snap_id and a.sql_id=ss.sql_id
 and s.begin_interval_time > sysdate -1
    group by 
    ss.sql_text,a.SQL_ID
order by 
    sum(CPU_TIME_DELTA) desc)
where rownum<20;



TOP IO SQL

You can find TOP IO SQL for last 24 hours with following script.

 

select * from 
(
SELECT /*+LEADING(x h) USE_NL(h)*/ 
       h.sql_id
,      SUM(10) ash_secs
FROM   dba_hist_snapshot x
,      dba_hist_active_sess_history h
WHERE   x.begin_interval_time > sysdate -1
AND    h.SNAP_id = X.SNAP_id
AND    h.dbid = x.dbid
AND    h.instance_number = x.instance_number
AND    h.event in  ('db file sequential read','db file scattered read')
GROUP BY h.sql_id
ORDER BY ash_secs desc )
where rownum<10;



You can find TOP 10 SQL for last 1 hour with following script.

 

select * from (
select active_session_history.sql_id,
 dba_users.username,
 sqlarea.sql_text,
sum(active_session_history.wait_time +
active_session_history.time_waited) ttl_wait_time
from v$active_session_history active_session_history,
v$sqlarea sqlarea,
 dba_users
where 
active_session_history.sample_time between sysdate -  1/24  and sysdate
  and active_session_history.sql_id = sqlarea.sql_id
and active_session_history.user_id = dba_users.user_id
 group by active_session_history.sql_id,sqlarea.sql_text, dba_users.username
 order by 4 desc )
where rownum <11;




 

 

 

You can check Top Oracle database wait events in Cache which is v$ queries with below script.

select  wait_class,
       sum(total_waits), sum(time_waited)
    from gv$session_wait_class
    where wait_class !='Idle'
    group by wait_class
    order by 3 desc;


You can check Top Oracle database wait events from Active session history which is v$active_session_history queries with below script.

select * from (
select active_session_history.event,
sum(active_session_history.wait_time +
active_session_history.time_waited) ttl_wait_time
from gv$active_session_history active_session_history
where active_session_history.event is not null
group by active_session_history.event
order by 2 desc)
where rownum <= 10;



 

 

You can check Top Oracle database wait events at specific intervals. You should type date and SNAP_ID

select snap_id,begin_interval_time,end_interval_time
from dba_hist_snapshot
where to_char(begin_interval_time,'DD-MON-YYYY')='20-FEB-2019'
and EXTRACT(HOUR FROM begin_interval_time) between 8 and 10;

select * from (
select active_session_history.event,
sum(active_session_history.wait_time +
active_session_history.time_waited) ttl_wait_time
from dba_hist_active_sess_history active_session_history
where event is not null
and SNAP_ID between 34411 and 34431
group by active_session_history.event
order by 2 desc)
where rownum<10;



 

 

 

To find any SQL’s SQL_ID and other SQL informations in the cache, use following SQL. Following query will find if related SQL exists in the cache, if not exists it will not find.

select * from gv$sql where sql_text like '%DEVECI%';

 

To search any SQL historical in Oracle database you may use following SQL. Just change begin Interval time column and SQL_TEXT column.

 

SELECT STAT.SQL_ID, SQL_TEXT, PLAN_HASH_VALUE, PARSING_SCHEMA_NAME, ELAPSED_TIME_DELTA, 
STAT.SNAP_ID, SS.END_INTERVAL_TIME, EXECUTIONS_DELTA FROM DBA_HIST_SQLSTAT STAT, 
DBA_HIST_SQLTEXT TXT, DBA_HIST_SNAPSHOT SS WHERE STAT.SQL_ID = TXT.SQL_ID AND
STAT.DBID = TXT.DBID AND SS.DBID = STAT.DBID AND SS.INSTANCE_NUMBER = STAT.INSTANCE_NUMBER 
AND STAT.SNAP_ID = SS.SNAP_ID AND
SS.BEGIN_INTERVAL_TIME >= sysdate-31 AND
UPPER(SQL_TEXT) LIKE '%DEVECI%' ORDER BY ELAPSED_TIME_DELTA DESC;



 

You can find average Active session of database with following script.

 

SELECT 'Load',
CASE
WHEN ( ( CAST (end_time.sample_time AS DATE)
- CAST (start_time.sample_time AS DATE))
* 24
* 60
* 60) = 0
THEN
0
ELSE
ROUND (
( COUNT (ash.sample_id)
/ ( ( CAST (end_time.sample_time AS DATE)
- CAST (start_time.sample_time AS DATE))
* 24
* 60
* 60)),
2)
END
AS Average_Active_Session
FROM (SELECT MIN (sample_time) sample_time
FROM v$active_session_history ash
WHERE sample_time BETWEEN SYSDATE - 1 / 1440 AND SYSDATE) start_time,
(SELECT MAX (sample_time) sample_time
FROM gv$active_session_history
WHERE sample_time BETWEEN SYSDATE - 1 / 1440 AND SYSDATE) end_time,
gv$active_session_history ash
WHERE ash.sample_time BETWEEN start_time.sample_time
AND end_time.sample_time
GROUP BY end_time.sample_time, start_time.sample_time;




To list all User Sessions not Background, use following scripts. This script will list you just only User type sessions and their detais.

select * FROM gv$session s, gv$process p
WHERE s.paddr = p.addr(+)
and s.TYPE ='USER' and s.username!='SYS';

 

You can list how many Active and Inactive User sessions are in the Oracle database with following script.

select count(*) FROM gv$session s, gv$process p
WHERE s.paddr = p.addr(+)
and s.TYPE ='USER' and s.username!='SYS';


You can list only Active User sessions without sys user with following script

select count(*) FROM gv$session s, gv$process p
WHERE s.paddr = p.addr(+)
and s.TYPE ='USER' and s.username!='SYS' and status='ACTIVE';

 

You can list only Inactive User sessions without sys user with following script

select count(*) FROM gv$session s, gv$process p
WHERE s.paddr = p.addr(+)
and s.TYPE ='USER' and s.username!='SYS' and status='INACTIVE';



You can list all user sessions which are ACTIVE state more than 600 Second with following script.

select count(*) FROM gv$session s, gv$process p
WHERE s.paddr = p.addr(+)
and s.TYPE ='USER' and s.username!='SYS' and status='ACTIVE' and last_call_et > 600
   

 

If you don’t use bind variables in the SQL queries then Oracle will know similar sqls differently like following.

select * from customer where id=63;

select * from customer where id=34;

Above queries are almost same, just id variable is different. But Oracle optimizer will evaluate these SQLs like different SQL.

If you use bind variable instead of literal like following then Oracle will evaluate as same SQL and will use same execution plan and won’t be hard parse in Oracle.

 

variable SYS_B_0 number;
exec :SYS_B_0:= 63

select * from customer where id= :SYS_B_0;



You can find out all queries which are not using bind variables with following script. You can see more queries with changing row nums of script.

 

Select * 
from (
With subs as
(SELECT /*+ materialize */
m.sql_id, k.*, m.SQL_TEXT, m.SQL_FULLTEXT
FROM (SELECT inst_id,
parsing_schema_name AS user_name,
module,
plan_hash_value,
COUNT(0) copies,
SUM(executions) executions,
SUM(round(sharable_mem / (1024 * 1024), 2)) sharable_mem_mb
FROM gv$sqlarea
WHERE executions < 5
AND kept_versions = 0
GROUP BY inst_id, parsing_schema_name, module, plan_hash_value
HAVING COUNT(0) > 10
ORDER BY COUNT(0) DESC) k
LEFT JOIN gv$sqlarea m
ON k.plan_hash_value = m.plan_hash_value
WHERE k.plan_hash_value > 0)
select distinct ki.inst_id,
t.sql_id,
ki.sql_text,
t.plsql_procedure,
ki.user_name,
sum(ki.copies) copies,
sum(ki.executions) executions,
sum(ki.sharable_mem_mb) sharable_mem_mb
from (select sql_id,
program_id,
program_line#,
action,
module,
service,
parsing_schema_name,
round(buffer_gets / decode(executions, 0, 1, executions)) buffer_per_Exec,
row_number() over(partition by sql_id order by program_id desc, program_line#) sira,
decode(program_id,
0,
null,
owner || '.' || object_name || '(' || program_line# || ')') plsql_procedure
from gv$sql a, dba_objects b
where a.program_id = b.object_id(+)) t,
subs ki
where ki.sql_id = t.sql_id
and t.sira = 1
group by ki.inst_id,
t.sql_id,
ki.sql_text,
t.plsql_procedure,
ki.user_name
order by sum(ki.executions) desc
)
where rownum < 51;   

 

 

You will find object detail of queries which is not using bind variables.

 

With subs as
(SELECT /*+ materialize */
   m.sql_id, k.*, m.SQL_TEXT, m.SQL_FULLTEXT
    FROM (SELECT inst_id,
                 parsing_schema_name AS user_name,
                 module,
                 plan_hash_value,
                 COUNT(0) copies,
                 SUM(executions) executions,
                 SUM(round(sharable_mem / (1024 * 1024), 2)) sharable_mem_mb
            FROM gv$sqlarea
           WHERE executions < 5
             AND kept_versions = 0
           GROUP BY inst_id, parsing_schema_name, module, plan_hash_value
          HAVING COUNT(0) > 10
           ORDER BY COUNT(0) DESC) k
    LEFT JOIN gv$sqlarea m
      ON k.plan_hash_value = m.plan_hash_value
   WHERE k.plan_hash_value > 0)
select *
  from (select sql_id,
               program_id,
               program_line#,
               action,
               module,
               service,
               parsing_schema_name,
               round(buffer_gets / decode(executions, 0, 1, executions)) buffer_per_Exec,
               row_number() over(partition by sql_id order by program_id desc, program_line#) lines,
               decode(program_id,
                      0,
                      null,
                      owner || '.' || object_name || '(' || program_line# || ')') plsql_procedure
          from gv$sql a, dba_objects b
         where a.program_id = b.object_id(+)) t,
       subs ki
where ki.sql_id = t.sql_id
   and lines = 1;




You can access the third Oracle DBA scripts related to Blocking Sessions and Lock Kill Scripts with following link.

Find Blocking Sessions and Lock Kill Scripts & Locked Objects | Oracle DBA Scripts All in One -3

 

 

Do you want to learn Oracle Database Performance Tuning detailed, then read the following articles.

Performance Tuning and SQL Tuning Tutorial in the Oracle Database

 

About Mehmet Salih Deveci

I am Founder of SysDBASoft IT and IT Tutorial and Certified Expert about Oracle & SQL Server database, Goldengate, Exadata Machine, Oracle Database Appliance administrator with 10+years experience.I have OCA, OCP, OCE RAC Expert Certificates I have worked 100+ Banking, Insurance, Finance, Telco and etc. clients as a Consultant, Insource or Outsource.I have done 200+ Operations in this clients such as Exadata Installation & PoC & Migration & Upgrade, Oracle & SQL Server Database Upgrade, Oracle RAC Installation, SQL Server AlwaysOn Installation, Database Migration, Disaster Recovery, Backup Restore, Performance Tuning, Periodic Healthchecks.I have done 2000+ Table replication with Goldengate or SQL Server Replication tool for DWH Databases in many clients.If you need Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS Consultancy and Training you can send my email adress [email protected].-                                                                                                                                                                                                                                                 -Oracle DBA, SQL Server DBA, APPS DBA,  Exadata, Goldengate, EBS ve linux Danışmanlık ve Eğitim için  [email protected] a mail atabilirsiniz.

8 comments

  1. Really helpful brother.

  2. Thanks for the scripts,

    Can you please provide RAC db performance sql queries like, wait events across the instances, blocking sessions instance wise and final blocker

Leave a Reply

Your email address will not be published. Required fields are marked *