#!/usr/bin/ksh # program smenu_desc_idx.sh # Author : Bernard Polarski : 07/12/99 # rewritten 23 september 2005 # Bart Debersaques : Add size on index # bpa : Add count on unusable indexes # bpa : add -inv options for quick list all invalids #set -x #--------------- comments section --------------------- # This script is part of the module 3 (DB utilities) # in smenu # Purpose : List all indexes for a user # a table #--------------- Environement section --------------------- # SBIN2=$SBIN/module2 SBINS=$SBIN/scripts HOST=`hostname` #--------------- Test variables section --------------------- PROMPT=" prompt . idx -u [-c] All table/indexes for the schema prompt . idx -t [-s][-c] -s for size(m) -c count unusable sub indx prompt . idx -i [-p [-w]] -p show sub part -w row count -g show stats prompt . idx -h for a more detailed help prompt . U = Unique P=Degree of parallelism S=Status prompt " function help { cat < : List all index in the schema sorted by table add -c to list indexes invalid for the user : idx -u SCOTT -c -t : List all index for a table -s display the size info or -c display unusable sub index part count ie) idx -t -s idx -t
-c -i : -p will add index sub partitions info such as status, tbs and size for each sub idx -i -p -w to replace tbs with rows info idx -i -p -w -fb will add the text of the function based index -ix : Alternate info on index from ixora -inv : List invalid indexes, partitions and subpartitions, order by owner -sinv : Generate Rebuild statement for ll invalid indexes, partitions and subpartitions -cf : Show clustering factor in percentage. The lower is the best, 100% is the worst -hg : Show system overal histograms distribution among indexes Notes: Clustering factor : - if near the number of blocks, then the table is ordered : index entries in a single leaf block tend to point to rows in same data block - if near the number of rows, the table is randomly ordered : index entries in a single leaf block are unlikely to point to rows in same data block Global stats : For partitioned indexes, YES means statistics are collected for the INDEX as a whole NO means statistics are estimated from statistics on underlying index partitions or subpart. Pct_direct_access : For secondary indexes on IOTs, rows with VALID guess EOF } TR=${TR:-UCB} if [ "x-$1" = "x-" ];then help exit fi VAR_FIELD="to_char(LAST_ANALYZED,'DD-MM HH24:MI') la," CF_FIELD=" clustering_factor cf, " TIT_IDX_NAME_LEN=28 TIT_COL_NAME=20 TIT_TABLE_NAME=22 while [ -n "$1" ] do case $1 in -h ) help exit ;; -ix ) typeset -u var=$2; INDEX=$var; IX=TRUE; shift;; -hg ) HISTO=TRUE;; -i ) typeset -u var=$2 INDEX=$var shift;; -cf) CF_FIELD=" round(decode(b.num_rows,0,0,((CLUSTERING_FACTOR/(select blocks from dba_Tables where table_name ='&table_name' and table_owner='&table_owner' )) /(b.NUM_ROWS/(select blocks from dba_Tables where table_name =upper('&table_name') and table_owner=upper('&table_owner') ))))*100,1) pct ," BLOCKS="c.blocks," #AND_TABLES=" c.table_name = b.table_name and c.owner=b.table_owner and" DBA_TABLES=",dba_tables c " TIT_IDX_NAME_LEN=24 TIT_COL_NAME=17 TIT_TABLE_NAME=23;; -w ) PAR_SQL1="nvl(b.num_rows,a.num_rows) sel , nvl(b.distinct_keys,a.distinct_keys) dstk," ;; -p ) PAR_SQL1="lpad(nvl(b.tablespace_name,a.tablespace_name),25) tablespace_name, " PAR_SQL0=" set head on break on partition_position on partition_name on status on report on tablespace_name COL sel FORMAT 999999999 heading 'Num rows' COL dstk FORMAT 999999999 heading 'Distinct rows' COL partition_position FORMAT 9999 heading 'Part| Pos' COL fsize FORMAT 9999999 heading 'Size (m)' COL partition_name FORMAT A25 head 'Partition name' COL subpartition_name FORMAT A25 head 'System generated|Subartition name' COL tablespace_name FORMAT A25 justify c HEAD ' Tablespace name' col last_analyzed format A18 head 'Last Analyzed' col status format A8 comp sum of fsize on report select a.partition_position, a.partition_name, b.subpartition_name, substr(nvl(b.status,a.status),1,6) status," PAR_SQL2=" (nvl(b.leaf_blocks,a.leaf_blocks) * &fsize )/1024/1024 fsize, to_char(nvl(b.last_analyzed,a.last_analyzed),'DD-MM-YY HH24:MI') la from dba_ind_partitions a, dba_ind_subpartitions b where a.index_name = '$INDEX' and a.index_name = b.index_name (+) and a.partition_name=b.partition_name (+)" PAR_SQL3=" order by a.partition_name; " ;; -v ) set -x;; -t ) typeset -u var=$2 TABLE=" a.table_name ='$var' and " shift;; -s ) VAR_FIELD="(select sum(bytes/1024/1024) bytes from dba_segments where segment_name = b.index_name and owner = b.owner group by owner,segment_name) bytes," ;; -c ) VAR_FIELD=" (select count(1) cpt from dba_ind_subpartitions where status = 'UNUSABLE' and index_name = b.index_name) + (select count(1) cpt from dba_ind_partitions where status = 'UNUSABLE' and index_name = b.index_name) un ," # only limit selection to unusable index when '-u' is selected, not for -t if [ -z "$TABLE" ];then LIMIT0='select * from (' LIMIT1=" ) where un > 0" fi ;; -u ) OW1=$2 shift if [ "x-$TR" = "x-" ];then TR=`grep "^TR=" $SBIN/smenu.env | cut -f2 -d"="` fi if [ "x-$TR" = "x-UCB" ] ;then OWNER="'`echo $OW1 | tr '[a-z]' '[A-Z]'`'" else OWNER="'`echo $OW1 | tr a-z A-Z`'" fi OTHERWISE=" a.table_owner=$OWNER and " AND_OWNER=" and a.table_owner = $OWNER" AND_OWNER0=" and SEGMENT_owner = $OWNER" AND_I_OWNER=" and a.index_owner = $OWNER" AND_OOWNER=" and o.owner = $OWNER" ;; -inv ) LIST_INVALID=TRUE;; -sinv ) REBUILD_INVALID=TRUE;; -fb ) PAR_SQL0="select COLUMN_POSITION, COLUMN_EXPRESSION from DBA_IND_EXPRESSIONS a where INDEX_NAME = '$INDEX' $AND_OWNER;";; * ) help exit ; esac shift done if [ -n "$PAR_SQL0" ];then PAR_SQL="$PAR_SQL0 $PAR_SQL1 $PAR_SQL2 $AND_I_OWNER $PAR_SQL3" fi #--------------- Process section --------------------- #--------------- Get system password section --------------------- . $SBIN/scripts/passwd.env . ${GET_PASSWD} if [ "x-$CONNECT_STRING" = "x-" ];then echo "could no get a the password of $S_USER" exit 0 fi #--------------- Process section --------------------- #................................................ # list invalid indexes #................................................ if [ "$HISTO" = "TRUE" ];then sqlplus -s "$CONNECT_STRING" < 2 then 1 else 0 end) histograms, sum(case when max_cnt <= 2 then 1 else 0 end) no_histograms from ( select table_name, max(cnt) max_cnt from ( select table_name, column_name, count(*) cnt from dba_tab_histograms group by table_name, column_name ) group by table_name ) / EOF #................................................ # list invalid indexes #................................................ elif [ "$IX" = "TRUE" ];then INDEX=`echo $INDEX| $NAWK '{print (toupper($1))}'` #------------------------------------------------------------------------------- #-- #-- Script: index_access_paths.sql #-- Purpose: *** called from table_access_paths.sql *** #-- #-- Copyright: (c) Ixora Pty Ltd #-- Author: Steve Adams (http://www.ixora.com.au/scripts/sql/index_access_paths.sql) #-- Adapted to Smenu by B. Polarski #-------------------------------------------------------------------------------- # cat <