#!/usr/bin/ksh # set -xv # author : B. Polarski # program : smenu_gather_stat_tbl.ksh # date : 01 October 2005 # Apapted to Smenu by B. Polarski # Modified: 04 October HOST=`hostname` HOST=`echo $HOST | awk '{ printf ("%-+15.15s",$1) }'` # ----------------------------------------------------------------------------------------------------------------------- function help { more < -t [-p ] [-f] [-s ] [-o ] [-n ] -part [partname] -c -cl -cp -x -ka -size -skew -kc -lock|-unlock sta -u -i [-p ] [-s ] [-o ] [-n ] -part [partname] -cp -cl -x sta -del -t
-u -p : Percent sample on each objects (default to 5%) -part : Partition name -i : the index -t : the table -d : degree (default to 2x cpu) -o : can be different than the objects analyzed -f : Copy gathered statistics to sm_stattab. It is needed if you intend to export/import statistics -c : Set cascade=TRUE to gather statistics also on the indexes -g : granularity, values are : DEFAULT Gather global - and partition-level statistics PARTITION, SUBPARTITION, GLOBAL, ALL Gather all (subpart, part, and global) -u : the table(s) or index(es) owner. If only the owner is given, then gather stats for schema -v : verbose -x : execute the output of this scripts -del : Delete stats for a table Misc: sta -lr |-mod [-u] [-t
] ----- -lr : List last run of job dbms_gather_stat -mod : List table whose stats are stale and not anaylized since days -lock|-unlock : if table name is not given then lock/unlock stats at schema level Method opts params: ------------------- -ka : For table only; set the number of histogram buckets for all columns: -k 100 -kc : For table only; set the number of histogram buckets per each columns. Give the string list used by method_opt -size: Number of buckets method_opt -skew : Use Skew as argument for method_opt -col ..... -col gather stats only for columns name list Note : sta -fy start -int 10 # Start gathering system stat during the 10 next minutes ------ sta -u -l -s # Give types per object. sta -u -t -kc "for columns size 240" -p 100 # to give your own method ops or sta -u -t -col BANKACCOUNT_ID -size 250 -x Use tbl [-u ] -t
-s to see stats on column for a table System statistics: sta -fx | -dx/-dy OR sta -fy [start |stop] [-int ] ------------------ -fx : gather stat for fixed tables -dx : delete stat for fixed tables -fy : gather system statistics -dy : delete system statistics -y : export or import will also do system statistics -lp : List dbms_stat default parameters Imp/Export statistics: sta -e -u -y ---------------------- sta -e -s -f [-t
] [-i ] [-u ] -c -e : export stats to from schema -u , from table -t
or from index -i -a : import stats from into schema -u or into table -t
or -i -n -s : Table that will hold stat of the table. (default is sm_stattab) Tables statistics: sta -del -s [-t
] [-i ] [-u ] -c ------------------ sta -a -s [-t
] [-i ] [-u ] -c -n -o sta -u -l |-m [-s ] [-b ] -del : delete stats from and schema -u -n -t
-part [partname] -cp -cl -ci -cp : delete cascade to partitions if partname is NULL -cl : delete cascade to columns -ci : delete cascade to indexes -i -part [partname] -cp -l : list existing stat table and statid. With -s , gives details per type for each object -m : Create stat table given by -s
-b create stattable in TABLESPACE otherwise default is used -n : statid EOF exit } # ----------------------------------------------------------------------------------------------------------------------- if [ -z "$1" ];then help; exit fi typeset -u ftable typeset -u findex typeset -u fowner typeset -u fgran typeset -u fcasc typeset -u fstattatb typeset -u FVAR typeset -u COL_LIST unset l_part CHECK_STR="#DEFAULT#PARTITION#SUBPARTITION#GLOBAL#ALL#" CREATE_STATTAB=FALSE LIST_STAT=FALSE EXECUTE=FALSE EXPORT_STAT=FALSE IMPORT_STAT=FALSE STAT_SYSTEM=FALSE fdate=`date +%m%d%H%M` fperc=dbms_stats.auto_sample_size fgran='ALL' fcasc=FALSE fcpu=`$SBIN/module2/s1/smenu_list_init_param.sh -p cpu_count` fdegree=`expr $fcpu \* 2` while [ -n "$1" ] do case "$1" in -a ) IMPORT_STAT=TRUE;; -b ) FVAR=$2 TBS=", '$FVAR'" shift ;; -c ) fcasc=TRUE ;; -del ) fdel=TRUE ;; -cl ) DEL_CASC_COL=",cascade_columns => TRUE ";; -cp ) DEL_CASC_PART=",cascade_parts => TRUE ";; -col ) if [ -n "$COL_LIST" ];then COL_LIST="${COL_LIST}, $2" else COL_LIST="$2" fi shift ;; -d ) fdegree=$2 shift ;; -e ) EXPORT_STAT=TRUE; COPY_ST_STTAB=TRUE;; -g ) fgran=$2 if [ -n "${CHECK_STR##*$fgran*}" ];then echo "########################################" echo "Wrong granularity value " echo "########################################" echo "\n Must be in ; \n`echo $CHECK_STR |tr '#' '\n'`" help fi shift;; -h ) help;; -fx ) CHOICE=GFIX ; GET=TRUE;; -fy ) CHOICE=GSYS ; GET=TRUE if [ "$2" = "-x" -o -z "$2" ] ;then : else MODE=$2; shift fi;; -dy ) CHOICE=GSYS ; GET=FALSE ;; -dx ) CHOICE=GFIX ; GET=FALSE;; -i ) findex=$2 ; shift ;; -int ) INT_MINUTES=$2; shift ;; -l ) LIST_STAT=TRUE ;; -lr ) CHOICE=LIST_LAST_RUN ; fower=${S_USER:-SYS};; -lp ) CHOICE=LIST_PARAM ;; -ka ) METHOD_OPT=" ,method_opt=>'for all columns size $2'";shift ;; -kc ) METHOD_OPT=" ,method_opt=>'$2'";shift ;; -mod) CHOICE=LIST_NOT_ANALYZED_TBL if [ -n "$2" ];then if [ "$2" = "-u" -o "$2" = "-t" ];then : else NDAYS=$2 ; shift fi fi ;; -n ) l_fstatid=$2 ; shift ;; -o ) fstat_owner=$2 ; shift ;; -m ) CREATE_STATTAB=TRUE ;; -p ) fperc=$2 ; shift ;; -part ) l_part=$2 ; shift ;; -s ) l_fstattab=$2 ; shift ;; -size ) CSIZE=$2; shift ;; -skew ) SKEW=SKEW;; -t ) ftable=$2 ; shift ;; -u ) fowner=$2 ; shift ;; -v ) set -x ;; -x ) EXECUTE=TRUE ;; -y ) STAT_SYSTEM=TRUE ;; -f ) COPY_ST_STTAB=TRUE ;; -lock ) LOCK=TRUE ; unset UN ;; -unlock ) LOCK=TRUE ; UN=UN ;; * ) echo "Invalid argument $1" $help ;; esac shift done # ------------------------------------------------------------------------------------- function ret_part { arg=$1 cpt=$2 TYPE=$3 # value is TAB or IND if [ $cpt -gt 0 -a ! "$fgran" = "PARTITION" ];then case $arg in PART_NAME ) echo SUBPARTITION_NAME ;; DBA_TAB ) echo DBA_${TYPE}_SUBPARTITIONS ;; esac if [ "$fgran" = "ALL" -o "$fgran" = "SUBPARTITION" ];then : else echo "Garther stats for subpartitions are only done for Granularity = \"ALL\" or \"SUBPARTITION\"" echo "If you are not happy with that, you can send your instults at ceo@Oracle.com" echo "Aborting ==>" exit 0 fi else case $arg in PART_NAME ) echo PARTITION_NAME ;; DBA_TAB ) echo DBA_${TYPE}_PARTITIONS ;; esac fi } # ------------------------------------------------------------------------------------- function get_ind_nbr_part { var=`sqlplus -s "$CONNECT_STRING"< 0 and STALE_STATS = 'YES' order by dbta.last_analyzed desc; EOF exit # ................................................ # List existing stats tables in DB or per scheman # ................................................ elif [ "$CHOICE" = "LIST_LAST_RUN" ];then sqlplus -s "$CONNECT_STRING"<" exit fi nbr=`echo $fvar | wc -w` if [ ! $nbr -eq 1 ];then echo "Mutilple user (\"`echo $var | tr '\n' ' '`\") or non existent table ==> abort" echo "user -u " exit else fowner=`echo $fvar | awk '{print $1}'` if [ -z $fowner ];then echo "Owner is blank" exit 1 fi fi fi if [ -z "$l_fstatid" ];then var=`echo $ftable | cut -c1-12` fstatid=$var$fdate else fstatid=$l_fstatid AND_STATID=" and statid='$l_fstatid' " fi fstattab=${l_fstattab:-sm_stattab} fstat_owner=${fstat_owner:-$fowner} fpart=${l_part:-NULL} FOUT=$SBIN/tmp/gather_tbl_stats_${ftable}_${fowner}.log FIL_EXECUTE=$SBIN/tmp/sta_$fstab_$fowner.sql if [ "$EXECUTE" = "TRUE" ];then > $FIL_EXECUTE fi $SETXV # .................................... # Create the stattab table is required # .................................... if [ "$CREATE_STATTAB" = "TRUE" ];then sqlplus -s "$CONNECT_STRING"<> $FIL_EXECUTE do_execute fi exit fi #pol # .................................... # Export/import STATS # .................................... if [ "$EXPORT_STAT" = "TRUE" -o "$IMPORT_STAT" = "TRUE" ];then #set -x if [ "$EXPORT_STAT" = "TRUE" ];then IMXP=export else IMXP=import fi if [ "$fpart" = "NULL" ];then ST_PART=",partname=>NULL" else ST_PART=",partname=>'$fpart'" fi if [ "$STAT_SYSTEM" = "TRUE" ];then PROC=${IMXP}_system_stats # import_system_stats or export_system_stats elif [ -n "$ftable" ];then G_FTABLE="tabname=> '$ftable' ," G_CASCADE="cascade=> $fcasc ," G_OWNER="ownname=>'$fowner' ," PROC=${IMXP}_table_stats SQL="exec dbms_stats.${IMXP}_table_stats( ownname=>'$fowner', tabname=> '$ftable' $ST_PART, cascade=> $fcasc $METHOD_OPT $COPY_ST_STTAB) " echo "Doing $SQL" sqlplus -s "$CONNECT_STRING"< abort" fi exit fi # ******************************************************** # ******************************************************** # Gather stats for TABLE,INDEX or SCHEMA # ******************************************************** # # ******************************************************** # A) Gather stats for TABLE # ******************************************************** if [ -n "$ftable" ];then #set -x # .................................... # check if we will gather stats only # for some columns # .................................... A=1 if [ -n "$COL_LIST" ];then if [ -n "$CSIZE" ];then COL_SIZE=" size $CSIZE" fi if [ -n "$SKEW" ];then COL_SIZE=" size SKEWONLY" fi METHOD_OPT=", method_opt => 'For columns ${COL_LIST} $COL_SIZE'" elif [ -n "$METHOD_OPT" ];then METHOD_OPT="$METHOD_OPT" fi # .................................... # check if table is not partitioned : # .................................... var=`sqlplus -s "$CONNECT_STRING"<> $FIL_EXECUTE fi done else # ............................................. # No partitions or single (sub)pationtion # ............................................. if [ -n "$l_part" ];then ST_PARTNAME="partname=> '$l_part'," fi SQL="exec dbms_stats.gather_table_stats( ownname=>'$fowner', tabname=> '$ftable', Degree=> $fdegree, $ST_PARTNAME estimate_percent=> $fperc, granularity=>'$fgran', cascade=>$fcasc $COPY_ST_STTAB $METHOD_OPT) " echo $SQL if [ "$EXECUTE" = "TRUE" ];then echo $SQL >> $FIL_EXECUTE fi fi # ******************************************************** # B) INDEX # ******************************************************** elif [ -n "$findex" ];then # index # .................................... # check if Index is not partitioned : # .................................... var=`sqlplus -s "$CONNECT_STRING"<" exit 0 fi else PART_NAME=PARTITION_NAME DBA_TAB=DBA_IND_PARTITIONS fi # ............................................. # loop on partitions now to issue the statement # ............................................. LST_PART=`sqlplus -s "$CONNECT_STRING"<> $FIL_EXECUTE fi done else # ............................................. # No partitions # ............................................. if [ -n "$l_part" ];then ST_PARTNAME="partname=> '$l_part'," fi SQL="exec dbms_stats.gather_index_stats( ownname=>'$fowner', indname=> '$findex', $ST_PARTNAME estimate_percent=> $fperc $COPY_ST_STTAB) " echo $SQL if [ "$EXECUTE" = "TRUE" ];then echo $SQL >> $FIL_EXECUTE fi fi else SQL="exec dbms_stats.gather_schema_stats( ownname=>'$fowner', Degree=> $fdegree, estimate_percent=> $fperc $COPY_ST_STTAB) " echo $SQL if [ "$EXECUTE" = "TRUE" ];then echo $SQL >> $FIL_EXECUTE fi fi if [ "$EXECUTE" = "TRUE" ];then do_execute fi