#!/usr/bin/ksh # set -xv # author : B. Polarski # 02 Sept 2005 # Modified 08 Jun 2006 : Added dbms_xplan # 28 Jun 2006 : Added vi, vh, -sb # 27 May 2008 : Added option -vx # 16 Jun 2009 : Added automatic conversion from sql_id to hash_value and reverse # 09 Dec 2010 : Added iggy Fernandez 'show execution steps plan' # 23 Dec 2010 : renamed '-sb' to '-lb' ROWNUM=30 # --------------------------------------------------------------------------- # to update an outlines : update outln.ol$hints set hint_text='INDEX_RS_ASC(@"SEL$1" "TXN"@"SEL$1" ("TXN"."EXT_TXN_ID" "TXN"."END_TIME"))' # where ol_name = 'SYS_OUTLINE_07120313083698728' and hint#=1 # get the value of ol_name and hint# with 'sx -stl' followed by 'sx -tn ' # ---------------------------------------------------------------------------------------------------------------- function check_HV_or_exit { if [ -z "$HASH_VALUE" ];then echo "corresponding hash_value is not found in memory anymore" exit fi } # ---------------------------------------------------------------------------------------------------------------- function get_sql_id_first_child { ret=`sqlplus -s "$CONNECT_STRING" < -c -cat # Create stored outlines for a given hash_value sx -crf -cat [-ot ] -u [-outln ] # Create stored outlines for SQL in file sx -ch -hv # Set hash value for OUTLINE_NAME sx -lso # list sql from V\$SQL which uses an Outline sx -lc [-cat ] # list stored outlines for category sx -ln [ OUTLINE_NAME ] [-outln ] # List hints for a given outline name. 'sx -lc' list existing outlines # default outln schema is OUTLN. use this if it is another schema sx -drc # Drop an outlines category sx -dr # Drop an outline sx -clone [-cat ] # for cloning, default category is DEFAULT sx -rfo # Resync the outline edited with memory sx -cl # reset used column in 'sx -lc' (dba_outlines.used) for an outline name sx -tr ][-outln ] # Transfer all outlines hints from to sx -pos OUTLINE_NAME OLD_POS NEW_POS # Move a hint line from one position to another sx -exp ][-outln ] # export the 3 outlines tables : OL\$ OL\$NODES OL\$HINTS in $SBIN/tmp sx -sp # show SQL Profiles sx -vs # Add stats from average execution (v\$sql_plan_statistic / v\$sql.executions ) sx -opt # Add optimizer environment for the given hash_value SQL plan statbilisation -> Stored Outlines/SQL profiles: sx -str [-u ] # List hash values which strings in the plan sx -stu # List operations present in v\$sql_plan Notes: -outln : use this only if the owner of the OL$ is not schema OUTLN Example : sx -crf F.SQL -cat MYCAT -ot F_OT -u LILI # Creates stored outlines for the sql in F.SQl, that addess tables visible # by schema LILI the stored outline will be named F_OT and be in category # MYCAT. if F.SQL is not in the current dir, then give full path EOF exit } # ---------------------------------------------------------------------------------------------------------------- function help { cat < -a -c # Show plan sx -pl # list hash_value, sql_id for a given plan_hash_value sx -l -u -tim -gets -cost # list plans, show multiples plans/sql_id; sort -tim:active time; -gets -cost sx -s -o -c # use sql_id 10g+ sx -vl # Add stats from last execution (v\$plan_statistic ) sx -vx [-c ] -p # another mix of v\$sql_plan and v\$sql_plan_statistics. -p : show partitions start/stop sx -lb # show bind variable sample (10g)+ sx -f -ev -level # set events (10046|53 etc..) before executing file sx -ed # edit tracefile whose number was given by '-f' sx -stp -c # Show execution plan steps sx -vh # Conversion : return sql_id for a given hash_value sx -vi # Conversion : return hash_value for a given sql_id Notes: -len : set the len of the sql_text column -v : Verbose : output sql text that the 'sx' command will use. Default is silent -f : execute sql in file. -c : SQL Child number (used in v$sql) default is 0 -s : Show plain with dbms_xplan.display_cursor -level : event level, default is 12, relevant only with -f -l : List all SQL present in v\$sql_plan -a : List access path and filter -u : restric plan to -dup : show sqlid with or more duplicate plan. default is 1 -rn : Limit number or rows to display, default is 30 -ev : set event in session while executing sql given by -f, default is 10053 -o : where is a choice of format 1 : Basic Displays the minimum information 2 : Typical Displays Partition pruning, parallelism and predicates if available 3 : Serial Like TYPICAL except that the parallel information is not displayed 4 : All Display all levels 5 : Runstats_last Displays the runtime statistics for the last execution of the cursor. (requires init.ora statistics_level=ALL) 6 : Runstats_TOT Displays the total aggregated runtime statistics for all executions (req. init.ora statistics_level=ALL) 7 : Outlines Display outlines used by the sql 8 : Advanced Display all available data about this sql default FORMAT is Typical For explain plans, 'sx' will first count the number of plans for a given SQL and display the number of the lowest child It will then try to display the plan for child 0, which is default. If there is no plan use the value of min to see the first one and query v\$sql_plan for other childs number. if there are multple childs, use sx -c to see each child plan EOF exit } # --------------------------------------------------------------------------- if [ "$1" = "-h" ];then help fi if [ -z "$1" ];then help fi METHOD=PLAN FORMAT=TYPICAL EV_NUM=10053 EV_LEVEL=12 typeset -u F_USER FLEN=50 HOST=`hostname` HOST=`echo $HOST | awk '{ printf ("%-+15.15s",$1) }'` unset TITTLE unset_presql=FALSE OLSCHEMA=OUTLN while [ -n "$1" ] do case "$1" in -a ) METHOD=AC1 ;; -lb ) METHOD=BIND; SQL_ID=$2; shift;; -c ) CHILD=$2;shift;; -cat ) CATEGORY=`echo $2|awk '{print toupper ($1) }'`; shift ;; # too much compat problems with typset -u -cl ) METHOD=CLEAN_USED; OT_NAME=`echo $2|awk '{print toupper($1)}'`; shift; TITTLE="Clear used col for $CATEGORY" ;; -ch ) METHOD=CH_HV ; OT_NAME=$2 ; shift ;; -clone ) METHOD=CLONE; OLD=$2 ; NEW=$3;shift; shift ;; -cro ) METHOD=CR_OUTLN; HASH_VALUE=$2; shift ;; -crf ) METHOD=CRF_OUTLN; SQLFILE=$2; shift ;; -drc ) METHOD=DROPCAT ; CATEGORY=`echo $2|awk '{print toupper($1)}'`; shift ;TITTLE="drop outlines category $CATEGORY" ;; -dr ) METHOD=DROPOL ; OT_NAME=`echo $2|awk '{print toupper($1)}'`; shift ;TITTLE="drop outlines category $CATEGORY" ;; -dup ) MAX_PLAN=$2 ; shift ;; -ed ) METHOD=TRC; TRC=$2; shift ;; -ev ) EV_NUM=$2; shift ;; -exp ) METHOD=EXP_STO ;; -f ) FFILE=$2;shift if [ ! -f "$FFILE" ];then echo "Cannot find $FFILE" exit fi METHOD=FILE;; -gets) ORDER=gets;; -tim ) ORDER=time;; -cost) ORDER=cost;; -h ) help ;; -hv ) HASH_VALUE=$2 ; shift ;; -i ) METHOD=PLAN_SQL_ID; SQL_ID=$2; shift ;; -len ) FLEN=$2 ; shift ;; -l ) METHOD=LIST_PLAN;; -lc ) METHOD=LIST_OUTLN ; TITTLE="List outlines" ;; -level ) EV_LEVEL=$2; shift ;; -ln ) METHOD=LIST_HINT; OT_NAME=$2 ; shift ;; -lso ) METHOD=LIST_SQL_OUTLN ;; -ot ) OT_NAME=`echo $2|awk '{print toupper($1)}'`; shift ;; -opt ) METHOD=OPTIM_ENV ; HASH_VALUE=$2 ; shift ;; -p ) PART_START_STOP=TRUE;; -pl ) METHOD=PL; PL_HV=$2; shift ;; -pos ) METHOD=CHG_POS; OT_NAME=$2; OLD_POS=$3 ; NEW_POS=$4; shift; shift;shift ;; -rfo ) METHOD=REFRESH_OL ; OT_NAME=$2; shift;; -rn ) ROWNUM=$2; shift;; -s ) METHOD=DBMS; SQL_ID=$2; shift ;; -sp ) METHOD=SQL_PROFILE;; -stp ) METHOD=STEPS ; SQL_ID="$2" ; shift ;; -str ) METHOD=STR ; STRING="$2" ; shift ;; -stru ) METHOD=STRU ;; -tr ) METHOD=CP_OL; SOURCE=$2;TARGET=$3;shift ; shift ;; -v ) VERBOSE=TRUE ;; -vh ) METHOD=VH; HASH_VALUE=$2 ; shift;; -vi ) METHOD=VI; SQL_ID=$2 ; TITTLE="List bind variable value for sql_id"; shift;; -vl ) METHOD=VLAST; HASH_VALUE=$2;shift;; -vs ) METHOD=VSTAT; HASH_VALUE=$2;shift;; -vx ) METHOD=XMS ; HASH_VALUE=$2 if [ "$3" = "-c" ];then if [ -n "$4" ];then SQL_CHILD=$4; shift; shift ; fi fi shift;; -u ) F_USER=$2; AND_OWNER=" and u.username='$F_USER'"; shift;; -o ) VAR=$2; case $VAR in 1) FORMAT=BASIC;; 2) FORMAT=TYPICAL;; 3) FORMAT=SERIAL;; 4) FORMAT='ALL +PEEKED_BINDS';; 5) FORMAT=RUNSTATS_LAST;; 6) FORMAT=RUNSTATS_TOT;; 7) FORMAT=OUTLINE ;; 8) FORMAT=ADVANCED ;; esac shift ;; -outln) OLSCHEMA=$2 ; shift ;; -h1 ) help1; exit ;; * ) HASH_VALUE=$1;; esac shift done # -------------------------------------------------------------------------- . $SBIN/scripts/passwd.env . ${GET_PASSWD} SYS $ORACLE_SID if [ "x-$CONNECT_STRING" = "x-" ];then echo "could no get a the password of $S_USER" exit 0 fi HASH_VALUE=`get_hash_value $HASH_VALUE` # -------------------------------------------------------------------------- if [ -n "$CHILD" ];then AND_CHILD_NUMBER=" and child_number = $CHILD" AND_A_CHILD_NUMBER=" and a.child_number = $CHILD" fi if [ -z "$TITTLE" ];then TITTLE="Explain plan for query hash_value" fi # -------------------------------------------------------------------------- # Show SQL optimizer enviromentment # -------------------------------------------------------------------------- if [ "$METHOD" = "STEPS" ];then # a very interresting attempt to demonstrate executions steps. this takes in a account # the last discussion on bushy tree plan whichd do not follow the deep left trees rule. # Copyright 2010 Iggy Fernandez : http://iggyfernandez.wordpress.com/2010/11/26/explaining-the-explain-plan-using-pictures/ SQL_ID=`get_sql_id $SQL_ID` if [ -z "$CHILD" ];then echo "No child given, retrieving from DB first child" RET=`get_sql_id_first_child $SQL_ID` CHILD=`echo "$RET" | tr -d '\n' | tr -d '\r' | awk '{print $1}'` fi CHILD=${CHILD:-0} SQL=" SET linesize 1000 pagesize 0 echo off feedback off verify off SET time off timing off sqlblanklines on col EXECUTION_SEQUENCE# for 999 head 'Step' col FID form a5 head 'Id in|plan' justify c col line form a140 -------------------------------------------------------------------------------- -- First retrieve the basic data from V$SQL_PLAN_STATISTICS_ALL. -- Modify this subquery if you want data from a different source. -------------------------------------------------------------------------------- WITH plan_table AS ( SELECT id, parent_id, object_name, operation, options, last_starts, last_elapsed_time / 1000000 AS last_elapsed_time, cardinality, last_output_rows, last_cr_buffer_gets + last_cu_buffer_gets AS last_buffer_gets, last_disk_reads FROM v\$sql_plan_statistics_all WHERE sql_id = '$SQL_ID' AND child_number = '$CHILD' ), -------------------------------------------------------------------------------- -- Determine the order in which steps are actually executed -------------------------------------------------------------------------------- execution_sequence AS ( SELECT id, ROWNUM AS execution_sequence# FROM plan_table pt1 START WITH -- Start with the leaf nodes NOT EXISTS ( SELECT * FROM plan_table pt2 WHERE pt2.parent_id = pt1.id ) CONNECT BY -- Connect to the parent node pt1.id = PRIOR pt1.parent_id -- if the prior node was the oldest sibling AND PRIOR pt1.id >= ALL( SELECT pt2.id FROM plan_table pt2 WHERE pt2.parent_id = pt1.id ) -- Process the leaf nodes from left to right ORDER SIBLINGS BY pt1.id ), -------------------------------------------------------------------------------- -- Calculate deltas for elapsed time, buffer gets, and disk reads -------------------------------------------------------------------------------- deltas AS ( SELECT t1.id, t1.last_elapsed_time - NVL(SUM(t2.last_elapsed_time),0) AS delta_elapsed_time, t1.last_buffer_gets - NVL(SUM(t2.last_buffer_gets),0) AS delta_buffer_gets, t1.last_disk_reads - NVL(SUM(t2.last_disk_reads),0) AS delta_disk_reads FROM plan_table t1 LEFT OUTER JOIN plan_table t2 ON t1.id = t2.parent_id GROUP BY t1.id, t1.last_elapsed_time, t1.last_buffer_gets, t1.last_disk_reads ), -------------------------------------------------------------------------------- -- Join the results of the previous subqueries -------------------------------------------------------------------------------- enhanced_plan_table AS ( SELECT -- Items from the plan_table subquery plan_table.id, plan_table.parent_id, plan_table.object_name, plan_table.operation, plan_table.options, plan_table.last_starts, plan_table.last_elapsed_time, plan_table.cardinality, plan_table.last_output_rows, plan_table.last_buffer_gets, plan_table.last_disk_reads, -- Items from the execution_sequence subquery execution_sequence.execution_sequence#, -- Items from the deltas subquery deltas.delta_elapsed_time, deltas.delta_buffer_gets, deltas.delta_disk_reads, -- Computed percentages CASE WHEN (SUM(deltas.delta_elapsed_time) OVER () = 0) THEN (100) ELSE (100 * deltas.delta_elapsed_time / SUM(deltas.delta_elapsed_time) OVER ()) END AS delta_percentage_elapsed_time, CASE WHEN (SUM(deltas.delta_buffer_gets) OVER () = 0) THEN (100) ELSE (100 * deltas.delta_buffer_gets / SUM(deltas.delta_buffer_gets) OVER ()) END AS delta_percentage_buffer_gets, CASE WHEN (SUM(deltas.delta_disk_reads) OVER () = 0) THEN (100) ELSE (100 * deltas.delta_disk_reads / SUM(deltas.delta_disk_reads) OVER ()) END AS delta_percentage_disk_reads, CASE WHEN (SUM(deltas.delta_elapsed_time) OVER () = 0) THEN (100) ELSE (100 * plan_table.last_elapsed_time / SUM(deltas.delta_elapsed_time) OVER ()) END AS last_percentage_elapsed_time, CASE WHEN (SUM(deltas.delta_buffer_gets) OVER () = 0) THEN (100) ELSE (100 * plan_table.last_buffer_gets / SUM(deltas.delta_buffer_gets) OVER ()) END AS last_percentage_buffer_gets, CASE WHEN (SUM(deltas.delta_disk_reads) OVER () = 0) THEN (100) ELSE (100 * plan_table.last_disk_reads / SUM(deltas.delta_disk_reads) OVER ()) END AS last_percentage_disk_reads FROM plan_table, execution_sequence, deltas WHERE plan_table.id = execution_sequence.id AND plan_table.id = deltas.id -- Order the results for cosmetic purposes ORDER BY plan_table.id ) -------------------------------------------------------------------------------- -- Begin THE graph -------------------------------------------------------------------------------- SELECT distinct execution_sequence#,'('||id||')' fid, ' ' -- Line 2: Operations, options, object name, and starts || operation || CASE WHEN (options IS NULL) THEN ('') ELSE (' ' || options) END || CASE WHEN (object_name IS NULL) THEN ('') ELSE (' ' || object_name) END || CASE WHEN (last_starts > 1) THEN (' (Starts= ' || last_starts || ')') ELSE ('') END -- Line 3: Delta elapsed time and cumulative elapsed time || ' Ela= ' || CASE WHEN (delta_elapsed_time IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(delta_elapsed_time, '999,999,990.00')) || 's') END || ' (' || CASE WHEN (delta_percentage_elapsed_time IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(delta_percentage_elapsed_time, '990')) || '%') END || ')' || ' C.Ela=' || CASE WHEN (last_elapsed_time IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(last_elapsed_time, '999,999,990.00')) || 's') END || ' (' || CASE WHEN (last_percentage_elapsed_time IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(last_percentage_elapsed_time, '990')) || '%') END || ')' -- Line 4: Delta buffer gets and cumulative buffer gets || ' Gets=' || CASE WHEN (delta_buffer_gets IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(delta_buffer_gets, '999,999,999,999,990'))) END || ' (' || CASE WHEN (delta_percentage_buffer_gets IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(delta_percentage_buffer_gets, '990')) || '%') END || ')' || ' C.Gets=' || CASE WHEN (last_buffer_gets IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(last_buffer_gets, '999,999,999,999,990'))) END || ' (' || CASE WHEN (last_percentage_buffer_gets IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(last_percentage_buffer_gets, '990')) || '%') END || ')' -- Line 5: Delta disk reads and cumulative disk reads || ' Dsk Reads=' || CASE WHEN (delta_disk_reads IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(delta_disk_reads, '999,999,999,999,990'))) END || ' (' || CASE WHEN (delta_percentage_disk_reads IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(delta_percentage_disk_reads, '990')) || '%') END || ')' || ' C.Dsk Reads=' || CASE WHEN (last_disk_reads IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(last_disk_reads, '999,999,999,999,990'))) END || ' (' || CASE WHEN (last_percentage_disk_reads IS NULL) THEN ('0') ELSE (TRIM(TO_CHAR(last_percentage_disk_reads, '990')) || '%') END || ')' -- Line 6: Estimated rows and actual rows || 'E Rows=' || CASE WHEN (cardinality IS NULL) THEN '0' ELSE (TRIM(TO_CHAR(cardinality, '999,999,999,999,990'))) END || ' A Rows=' || CASE WHEN (last_output_rows IS NULL) THEN '0' ELSE (TRIM(TO_CHAR(last_output_rows, '999,999,999,999,990'))) END AS line FROM enhanced_plan_table -- START WITH parent_id = 0 -- CONNECT BY parent_id = PRIOR id order by execution_sequence# / " # -------------------------------------------------------------------------- # Show SQL optimizer enviromentment # -------------------------------------------------------------------------- elif [ "$METHOD" = "OPTIM_ENV" ];then unset_presql=TRUE SQL_ID=`get_sql_id $HASH_VALUE` SQL="COLUMN CN FORMAT 99 col name for a45 col value for a25 SET PAGESIZE 1000 lines 190 break on sql_id on report SELECT SQL_ID, CHILD_NUMBER CN, SUBSTR(NAME,1,45) NAME, SUBSTR(VALUE,1,25) VALUE, ISDEFAULT DEF FROM V\$SQL_OPTIMIZER_ENV WHERE SQL_ID='$SQL_ID' AND CHILD_NUMBER=0 ORDER BY NAME; " # -------------------------------------------------------------------------- # Explain a SQL statements with execution profile from library cache # -------------------------------------------------------------------------- elif [ "$METHOD" = "XMS" ];then if [ -z "$SQL_CHILD" ];then SQL_CHILD=% fi if [ "$SQL_CHILD" = "%" ];then AND_SQL_CHILD=" and to_char(p.child_number) like '%' " else AND_SQL_CHILD=" and p.child_number = $SQL_CHILD " fi if [ "$PART_START_STOP" = "TRUE" ];then P_START="p.PARTITION_START, p.partition_stop" else P_COST="p.io_cost io_cost, case when ps.last_disk_writes > 1048576 then lpad(to_char(round(ps.last_disk_writes/1048576,1)),6,' ')||'m' else lpad(to_char(ps.last_disk_writes),7,' ') end last_disk_writes" fi #------------------------------------------------------------------------------------- #-- File name: xmsh (eXplain from Memory with Statistics lookup by Hash value) #-- Author: Tanel Poder # Copyright of Mr. Tanel suppressed for this query is identical to Breitling's one # found in this is same script but comes 3 years later (see sx -vl) . The output is though more candy # adapted to smenu by bpa #------------------------------------------------------------------------------------- SQL=" set verify off heading off feedback off linesize 190 pagesize 5000 tab off heading on column child_number heading 'Ch|ld' format 99 break on child_number skip 1 column id heading Op|ID format 999 column id2 heading Op|ID format a6 column pred heading Pr|ed format a2 column optimizer heading Optimizer|Mode format a10 column plan_step heading Operation for a38 column object_name heading Object|Name for a20 column opt_cost heading Optim|Cost for 999999 column opt_card heading 'Estim.|rows' for a8 justify c column cpu_cost heading CPU|Cost for 999999 column io_cost heading IO|Cost for 999999 column last_output_rows heading ' Last exec|#rows|returned' for a10 justify c column last_cr_buffer_gets heading 'Consist| gets' for a8 column last_cu_buffer_gets heading 'Current| gets' for a8 column last_disk_reads heading 'Physic| reads' for a8 column last_disk_writes heading ' Physic| writes' for a8 column last_elapsed_time_ms heading 'ms spent' for 9999990.99 col partition_stop head 'Part|Stop' for a5 col partition_start head 'Part|Start' for a5 select --+ ordered use_nl(p ps) p.child_number child_number, case when p.access_predicates is not null then 'A' else ' ' end || case when p.filter_predicates is not null then 'F' else ' ' end pred, p.id id, lpad(' ',p.depth*1,' ')|| p.operation || ' ' || p.options plan_step, p.object_name object_name, round(ps.last_elapsed_time/1000,2) last_elapsed_time_ms, p.cost opt_cost, case when p.cardinality > 1048576 then lpad(to_char(round(p.cardinality/1048576,1)),6,' ')||'m' else lpad(to_char(p.cardinality),7,' ') end opt_card, case when ps.last_output_rows > 1048576 then lpad(to_char(round(ps.last_output_rows/1048576,1)),6,' ')||'m' else lpad(to_char(ps.last_output_rows),7,' ') end last_output_rows, case when ps.last_cr_buffer_gets > 1048576 then lpad(to_char(round(ps.last_cr_buffer_gets/1048576,1)),6,' ')||'m' else lpad(to_char(ps.last_cr_buffer_gets),7,' ') end last_cr_buffer_gets, case when ps.last_cu_buffer_gets > 1048576 then lpad(to_char(round(ps.last_cu_buffer_gets/1048576,1)),6,' ')||'m' else lpad(to_char(ps.last_cu_buffer_gets),7,' ') end last_cu_buffer_gets, case when ps.last_disk_reads > 1048576 then lpad(to_char(round(ps.last_disk_reads/1048576,1)),6,' ')||'m' else lpad(to_char(ps.last_disk_reads),7,' ') end last_disk_reads , $P_COST $P_START from v\$sql_plan p, v\$sql_plan_statistics ps where p.address = ps.address(+) and p.hash_value = ps.hash_value(+) and p.id = ps.operation_id(+) and p.hash_value = $HASH_VALUE $AND_SQL_CHILD and p.child_number= ps.child_number (+) order by p.child_number asc, p.id asc / prompt set feedback on " # -------------------------------------------------------------------------- # List type of o$eration in v$sql_plan # -------------------------------------------------------------------------- elif [ "$METHOD" = "STRU" ];then unset_presql=TRUE SQL=" col ops format a40 select distinct ops, count(*) cpt from (select operation||' '||options ops from v\$sql_plan) group by ops ; " # -------------------------------------------------------------------------- # List hash_value with $STRING in plan # -------------------------------------------------------------------------- elif [ "$METHOD" = "STR" ];then unset_presql=TRUE SQL=" col operation format a40 set pagesize 66 select distinct a.hash_value, c.cost final_cost,a.id, a.operation ||' '|| a.options operation , b.id, b.operation||' '|| b.options operation from v\$sql_plan a , v\$sql_plan b, v\$sql_plan c where a.operation||' '||a.options like upper('%$STRING%') and a.hash_value=b.hash_value and a.child_number = b.child_number and c.hash_value=b.hash_value and c.child_number = b.child_number and c.id=0 and b.id = (a.id + 1) ; " # -------------------------------------------------------------------------- # change HASH_VALUE for a given OT # -------------------------------------------------------------------------- elif [ "$METHOD" = "CH_HV" ];then unset_presql=TRUE SQL="prompt Doing update outln.ol\$ set HASH_VALUE=$HASH_VALUE where ol_name = upper('$OT_NAME');; update outln.ol\$ set HASH_VALUE=$HASH_VALUE where ol_name = upper('$OT_NAME');" # -------------------------------------------------------------------------- # List hash_value when a plan_hash_value is given # -------------------------------------------------------------------------- elif [ "$METHOD" = "PL" ];then unset_presql=TRUE SQL="col sql_text format a80 select a.hash_value, a.child_number, sql_id , (select executions from v\$sql where hash_value=a.hash_value and child_number=a.child_number) executions, (select sql_text from v\$sql where hash_value=a.hash_value and child_number=a.child_number) sql_text from v\$sql_plan a where a.plan_hash_value = $PL_HV and id = 0; " # -------------------------------------------------------------------------- # List SQL from v$sql using outlines # -------------------------------------------------------------------------- elif [ "$METHOD" = "CRF_OUTLN" ];then if [ ! -f "$SQLFILE" ];then echo " I need an sql file" exit fi if [ -n "$CATEGORY" ];then AND_CAT=" for category $CATEGORY " fi FTMP=$SBIN/tmp/cr_outln_$$.sql echo "create or replace outline $OT_NAME $AND_CAT on " > $FTMP cat $SQLFILE |sed '/^$/d' >> $FTMP tail -2 $FTMP | grep '/' if [ $? -eq 1 ];then echo "/" >> $FTMP fi echo "exit" >> $FTMP if [ -n "$F_USER" ];then S_USER=`echo $F_USER| tr '[a-z]' '[A-Z]'` . $SBIN/scripts/passwd.env . ${GET_PASSWD} $S_USER $ORACLE_SID if [ "x-$CONNECT_STRING" = "x-" ];then echo "could no get a the password of $S_USER" exit 0 fi fi sqlplus -s "$CONNECT_STRING" @$FTMP rm -f $FTMP exit # -------------------------------------------------------------------------- # List SQL from v$sql using outlines # -------------------------------------------------------------------------- elif [ "$METHOD" = "LIST_SQL_OUTLN" ];then unset_presql=TRUE SQL="col SQL_TEXT format a40 col OPTIMIZER_COST format 999999 head 'Opt|Cost' col EXECUTIONS head 'Execs' col old_hash_value head 'Old hash|Value' justify c col plan_hash_value head 'Plan hash|Value' justify c select a.sql_id,a.hash_value,a.child_number,a.plan_hash_value, a.old_hash_value,a.EXECUTIONS,OPTIMIZER_COST,a.LAST_ACTIVE_TIME,substr(a.SQL_TEXT,1,40) sql_text from v\$sql a where outline_category is not null ; " # -------------------------------------------------------------------------- # Change outlines position # -------------------------------------------------------------------------- elif [ "$METHOD" = "CHG_POS" ];then unset_presql=TRUE SQL=" prompt doing : DBMS_OUTLN_EDIT.CHANGE_JOIN_POS ( '$OT_NAME', $OLD_POS , $NEW_POS); exec DBMS_OUTLN_EDIT.CHANGE_JOIN_POS( '$OT_NAME', $OLD_POS , $NEW_POS); " # -------------------------------------------------------------------------- # Transfer outlines hints from one OTL to another # -------------------------------------------------------------------------- elif [ "$METHOD" = "CP_OL" ];then unset_presql=TRUE if [ -z "$SOURCE" ];then echo "I need a source outline name" exit else var=`sqlplus -s "$CONNECT_STRING" < ] " exit fi SQL=" set linesize 190 col hint_text format a50 col hint# format 9999 col stage# format 9999 col Table_pos format 9999 head 'Table|pos' justify c col table_name format a24 set long 32000 select HINT#, HINT_TEXT, STAGE# ,TABLE_NAME, TABLE_POS,round(COST,2) cost,CARDINALITY,bytes from $OLSCHEMA.ol\$HINTS where OL_NAME = '$OT_NAME' ; " # -------------------------------------------------------------------------- # List stored outlines # -------------------------------------------------------------------------- elif [ "$METHOD" = "LIST_OUTLN" ];then unset_presql=TRUE if [ -n "$CATEGORY" ];then AND_CAT=" AND category = upper('$CATEGORY') " fi SQL="COLUMN name FORMAT A30 COLUMN category FORMAT A20 col owner format a14 set long 32000 linesize 150 set long 40 SELECT a.owner,a.name, a.category, a.enabled,a.used,b.hash_value, a.sql_text FROM dba_outlines a , $OLSCHEMA.ol\$ b where a.name = b.ol_name $AND_CAT; " # -------------------------------------------------------------------------- # Create stored outlines # -------------------------------------------------------------------------- elif [ "$METHOD" = "CR_OUTLN" ];then unset_presql=TRUE SQL=" prompt exec DBMS_OUTLN.create_outline( hash_value => $HASH_VALUE, child_number => $CHILD, category => '$CATEGORY'); exec DBMS_OUTLN.create_outline( hash_value => $HASH_VALUE, child_number => $CHILD, category => '$CATEGORY'); " # -------------------------------------------------------------------------- # Performance v$sql_plan_statistics # -------------------------------------------------------------------------- elif [ "$METHOD" = "VSTAT" ];then ret=`sqlplus -s "$CONNECT_STRING" <' to view stats and plan for one child\n" sqlplus -s "$CONNECT_STRING" <