Code Listings

  1. bind.sql - displays code that apparently doesn't use bind variables
  2. c8.sql - displays the high read code in the SQL cache
  3. c9.sql - displays the high read code in the SQL cache
  4. demo1.sql - For training purposes, demonstrates that NOT IN doesn't cope with NULLs
  5. ind.sql - Shows what columns are indexed
  6. spid.sql - Shows what sid is related to a unix shadow process id
  7. sql.sql - displays SQL and other info on sessions currently active or active within the last minute
  8. sw.sql - Shows what sessions are waiting on
  9. t.sga - displays the sga and pga values for all databases on a server
  10. trace.sql - Not a script as such, rather a list of useful commands and scripts to use for tracing etc.
::::::::::::::
bind.sql
::::::::::::::
--
-- Author: Andrew Fraser
-- Date: 13 June 2008
-- Name: bind.sql
-- Purpose: displays code that apparently doesn't use bind variables
-- Notes:
--
select substr(sql_text,1,30), sum(executions), count(*)
from v$sql
group by substr(sql_text,1,30)
having count(*) > 50
order by 3
/
::::::::::::::
c8.sql
::::::::::::::
--
-- Author: Andrew Fraser
-- Date: 13 June 2008
-- Name: c8.sql
-- Purpose: displays the high read code in the SQL cache
-- Notes: Vary the threshold to suit
--        Statspack has this also (if it is set up to run). In 10g AWR has this and runs by default.
--        9i and above can use elapsed_time
--        But 8i and below has to use either buffer_gets or disk_reads instead
--        With 10g, ?/rdbms/admin/sqltrpt should be used in preference to this script
--
set pages 9999
spool c.lst
select disk_reads, executions, disk_reads/greatest(executions,1) reads_per_exec, sql_text
from v$sql
where disk_reads > 100000
order by 3 desc
/
spool off
ed c.lst
::::::::::::::
c9.sql
::::::::::::::
--
-- Author: Andrew Fraser
-- Date: 13 June 2008
-- Name: c9.sql
-- Purpose: displays the high read code in the SQL cache
-- Notes: Statspack has this also (if it is set up to run). In 10g AWR has this and runs by default.
--        9i and above can use elapsed_time
--        But 8i and below has to use either buffer_gets or disk_reads instead
--        With 10g, ?/rdbms/admin/sqltrpt should be used in preference to this script
--
set pages 9999
spool c.lst
select secs, executions, secs_per_exec, sql_text
from (
  select elapsed_time/1000000 secs, executions, elapsed_time/1000000/greatest(executions,1) secs_per_exec, sql_text,
    rank() over ( order by elapsed_time/1000000/greatest(executions,1) desc ) spe_rank
  from v$sql )
where spe_rank <= 10
/
spool off
ed c.lst
::::::::::::::
demo1.sql
::::::::::::::
--
-- Author: Andrew Fraser
-- Date: 13 June 2008
-- Name: demo1.sql
-- Purpose: For training purposes, demonstrates that NOT IN doesn't cope with NULLs
-- Notes: 
--
set echo on
create table t1 (c1 number) ;
create table t2 (c2 number) ;
insert into t1 values ( 1 ) ;
insert into t1 values ( 2 ) ;
insert into t2 values ( 1 ) ;
select * from t1 where c1 not in ( select c2 from t2 ) ;
select * from t1 where not exists ( select null from t2 where c1 = c2 ) ;
insert into t2 values ( null ) ;
select * from t1 where c1 not in ( select c2 from t2 ) ;
select * from t1 where not exists ( select null from t2 where c1 = c2 ) ;
select * from t1 where c1 not in ( select c2 from t2 where c2 is not null ) ;
drop table t1 ;
drop table t2 ;
set echo off
::::::::::::::
ind.sql
::::::::::::::
--
-- Author: Andrew Fraser
-- Date: 20 June 2008
-- Name: ind.sql    
-- Purpose: Shows what columns are indexed
--
set pages 9999 lines 132
col column_position form 9 head Pos
col column_name form a30
col column_expression form a30
break on table_name on index_name
select c.table_name, c.index_name, c.column_position, c.column_name, e.column_expression
from dba_ind_columns c, dba_ind_expressions e
where c.index_name = e.index_name(+)
and c.index_owner = e.index_owner(+)
and c.table_name = e.table_name(+)
and c.column_position = e.column_position(+)
and c.table_name = 'MYTABLE'
and c.table_owner = 'MYOWNER'
order by 1,2,3
/
::::::::::::::
spid.sql
::::::::::::::
--
-- Author: Andrew Fraser
-- Date: 20 June 2008
-- Name: spid.sql
-- Purpose: Shows what sid is related to a unix shadow process id
--
set pages 9999 verify off
accept spid prompt "Unix Shadow Process ID: "
select s.sid
from v$session s, v$process p
where s.paddr=p.addr
and p.spid = &spid
/
::::::::::::::
sql.sql
::::::::::::::
--
-- Author: Andrew Fraser
-- Date: 13 June 2008
-- Name: sql.sql
-- Purpose: displays SQL and other info on sessions currently active or active within the last minute
-- Notes: "username is not null" excludes the background sessions
--
set pages 9999 lines 132
col username form a20
col osuser form a20
col program form a50
col minutes form 999
ALTER SESSION SET nls_date_format = 'Dy DD-Mon-YYYY HH24:MI:SS' ;
SELECT DISTINCT s.inst_id , s.sid , s.serial# , s.username , s.osuser , s.program || ' ' || s.module AS program
     , s.status , ROUND ( s.last_call_et / 60 ) AS minutes , s.logon_time
     , s.state , s.event , s.seconds_in_wait , s.sql_id , q.sql_text
  FROM gv$session s
  JOIN gv$sql q
    ON q.inst_id = s.inst_id
   AND q.sql_id = s.sql_id
 WHERE ( s.status = 'ACTIVE' OR last_call_et < 60 )  -- active in last minute
   AND s.username IS NOT NULL  -- exclude background sessions
 ORDER BY s.inst_id , s.sid
;
/* old versions before 10g need to include v$session_wait view: 
select distinct
s.sid, s.username, s.osuser, s.program||' '||s.module program,
s.status, s.last_call_Et/60 minutes, s.logon_time, w.state, w.event, w.seconds_in_wait ,
q.sql_text
from v$session s, v$sql q, v$session_wait w
where ( s.status = 'ACTIVE' or last_call_et < 60 )
and s.sql_hash_value = q.hash_value(+)
and s.sql_address = q.address(+)
and s.sid = w.sid
and s.username is not null
order by s.sid ; */
::::::::::::::
sw.sql
::::::::::::::
--
-- Author: Andrew Fraser
-- Date: 13 June 2008
-- Name: sw.sql
-- Purpose: Shows what sessions are waiting on
-- Notes: In 10g, there is also a v$session_wait_history view
--
set pages 9999 lines 112
col event form a60 head "Event - All Sessions"
select event, count(*), sum(seconds_in_wait)
from v$session_wait
group by event
order by 3 desc
/
col event form a60 head "Event - Excluding background sessions"
select w.event, count(*), sum(w.seconds_in_wait)
from v$session_wait w, v$session s
where w.sid = s.sid
and s.username is not null
group by w.event
order by 3 desc
/
::::::::::::::
t.sga
::::::::::::::
#
# Author: Andrew Fraser
# Date: 13 June 2008
# Name: t.sga
# Purpose: displays the sga and pga values for all databases on a server
# Notes: Database names with "_"'s in them will throw this script out. So those have to be queried manually.
#
export ORAENV_ASK=NO
for ORACLE_SID in `ps -ef|grep pmon|grep -v grep|awk -F_ '{print $3}'`
do
. oraenv
#sqlplus -s "/ as sysdba" <<e1
sqlplus -s / <<e1
set pages 0 head off feed off
select '$ORACLE_SID sga', sum(value)/1024/1024 mb from v\$sga
/
select '$ORACLE_SID pga', sum(value)/1024/1024 mb from v\$sesstat s, v\$statname n
where s.statistic# = n.statistic#
and n.name = 'session pga memory'
group by '$ORACLE_SID pga'
/
-- select '$ORACLE_SID sga_max_size', value/1024/1024 mb from v\$parameter where name = 'sga_max_size';
-- select '$ORACLE_SID pga_target', value/1024/1024 mb from v\$parameter where name = 'pga_aggregate_target';
e1
done
::::::::::::::
trace.sql
::::::::::::::
--
-- Author: Andrew Fraser
-- Date: 13 June 2008
-- Name: trace.sql
-- Purpose: Not a script as such, rather a list of useful commands and scripts to use for tracing etc.
--
set pages 9999 doc on
doc
Tracing your own session:
 alter session set timed_statistics=true ;
 alter session set max_dump_file_size=unlimited ;
 alter session set tracefile_identifier='MY_OPTIONAL_TEXT' ;
 alter session set events '10046 trace name context forever, level 8' ;
   /* code to be traced goes here */
 alter session set events '10046 trace name context off' ;
Tracing someone else's session:
 exec dbms_monitor.session_trace_enable ( session_id => 123 , serial# = 123 )
   /* and to switch it off: */
 exec dbms_monitor.session_trace_disable ( session_id => 123 , serial# = 123 )
In a RAC environment you must be connected to the same instance for those commands to take effect.
Old versions before 11g tracing someone else's session:
 exec sys.dbms_system.set_bool_param_in_session(sid,serial#,'timed_statistics',true)
 exec sys.dbms_system.set_int_param_in_session(sid,serial#,'max_dump_file_size', 2147483647)
 exec sys.dbms_system.set_ev(sid,serial#,10046,8,'')
   /* and to switch it off: */
 exec sys.dbms_system.set_ev(sid,serial#,10046,0,'')
Select session's to trace with SQL something like:
 SELECT inst_id , sid , serial# , username FROM gv$session WHERE ( status = 'ACTIVE' OR last_call_et < 60 ) ;
Output goes into a trace file in user_dump_dest
These trace files may be cat'd together. E.g.:
 cat 1.trc 2.trc 3.trc 4.trc > big.trc
 tkprof big big

Tkprof produces a .prf output from that. Sort on either fchela or exeela, depending on which is overall largest:

First run:

 tkprof [trace file] [output file]
Go to end of file, and see whether fetch or execute has largest elapsed time.

Then run either:

 tkprof [trace file] [output file] sort=fchela
 tkprof [trace file] [output file] sort=exeela
(If at all possible, use the latest version of tkprof, even with traces produced from an older version database, and even if that means copying trace files to different servers)

For more 10046 tracing options, see the More 10046 Tracing page

-------------------------------------------
Statspack for 8i and 9i:
@?/rdbms/admin/spreport - main report
@?/rdbms/admin/sprepsql - individual sql report, input the hash_value for the sql you want
@?/rdbms/admin/spcreate - installs statspack
exec perfstat.statspack.snap - manually take a new snapshot
AWR for 10g and above:
@?/rdbms/admin/awrrpt - main report
@?/rdbms/admin/awrsqrpt - report one one particular SQL statement, input the sql_id for the sql you want
@?/rdbms/admin/sqltrpt - lists top 15 statements, then tunes any sql statement, input the sql_id for the sql you want
Oracle Enterprise Manager Database Control default URL is http://server:1158/em

Explain plan:

 set pages 9999 lines 192
 col plan_plus_exp form a132
@?/rdbms/admin/utlxpls -- outputs explain plan
 set lines 132

@?/rdbms/admin/utlxplan - (9i and below only) installs explain_plan table. Best to do this as sys only and create public synonym
To set values for bind variables in sql*plus:
variable b1 varchar2(6) ;
exec :b1 := '2009'
-------------------------------------------
If you have accepted a sql profile from a tuning advisor recommandation like:
execute dbms_sqltune.accept_sql_profile(task_name => 'TASK_239607', replace => TRUE) ;
Then the regression commands to back it out are like:
select name from dba_sql_profiles ;
exec dbms_sqltune.drop_sql_profile('MYNAME')
-------------------------------------------
Get password values for connecting in as a user:
select password from dba_users where username = 'MYUSER' ; -- old versions up to 10g
set long 9999
select dbms_metadata.get_ddl ('USER', 'MYUSER') from dual ;  -- 11g and above
alter user myuser identified by temp_pass ;
conn myuser/temp_pass ;
alter user myuser identified by values 'STRING OF CHARACTERS FROM ABOVE' ;
-------------------------------------------
Index monitoring usage for all tables:
set pages 9999 lines 112
spool go.tmp
SELECT 'alter index '||owner||'.'||index_name||' monitoring usage ;'
from dba_indexes
where table_owner = 'MYSCHEMA'
order by 1
/
spool off
Documentation on index monitoring says:
The view V$OBJECT_USAGE can be queried for the index being monitored to see if the index has been used. The view contains a USED column whose value is YES or NO, depending upon if the index has been used within the time period being monitored. The view also contains the start and stop times of the monitoring period, and a MONITORING column (YES/NO) to indicate if usage monitoring is currently active.

Each time that you specify MONITORING USAGE, the V$OBJECT_USAGE view is reset for the specified index. The previous usage information is cleared or reset, and a new start time is recorded. When you specify NOMONITORING USAGE, no further monitoring is performed, and the end time is recorded for the monitoring period. Until the next ALTER INDEX...MONITORING USAGE statement is issued, the view information is left unchanged.