Last active
October 19, 2022 16:06
-
-
Save haballan/ff1ef68cd1be374acb0fe549026eb555 to your computer and use it in GitHub Desktop.
SCRIPT TO REBUILD A GIVEN TABLE AND ITS INDEXES USING ONLINE FEATURES DBMS_REDEFINITION/ONLINE REBUILD IF AVAILABLE OR OFFLINE REBUILD AS A FINAL RESORT http://dba-tips.blogspot.com/2019/05/rebuild-table-script-and-reclaim-wasted.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ######################################################################################################################################################### | |
# Ver 3.2 | |
# SCRIPT TO REBUILD A GIVEN TABLE AND ITS INDEXES USING ONLINE FEATURES DBMS_REDEFINITION/ONLINE REBUILD IF AVAILABLE OR OFFLINE REBUILD AS A FINAL RESORT | |
# ######################################################################################################################################################### | |
# | |
# # # # | |
# Author: Mahmmoud ADEL # # # # ### | |
# Created: 16-06-14 # # # # # | |
# | |
# Modified: 17-06-14 Inform the user if the DB is in Force Logging Mode. | |
# 16-09-14 Added Search Feature. | |
# 04-01-16 Added DEGREE OF PARALLELISM calculation. | |
# 11-04-19 Added ONLINE table rebuild for Oracle 12.2. | |
# 15-04-19 Added pctfree option to the rebuild command. | |
# 16-04-19 Added DBMS_REDEIFINITION to the list of rebuild options. | |
# 18-04-19 Added ALERTLOG notification when the DBMS_REDEIFINITION process reach to the Final Step: [Manual Mode] | |
# 21-04-19 Added COMPRESSION option to ALTER TABLE REBUILD option. | |
# 25-04-19 Added the check for the free space on the underlying tablespace. | |
# 05-05-19 Added PCTFREE option for DBMS_REDEIFINITION process | |
# 05-05-19 Fix the bug of not showing UNUSABLE INDEXES after the rebuild by using the outer join. | |
# 05-05-19 Increased DDL LOCK timeout to 5 minutes to avoid the failure of the rebuild operation due to failure to aquire a lock. | |
# 09-05-19 Included "WHENEVER SQLERROR EXIT" to the SQLPLUS script to terminate the rebuild if any stage return errors. | |
# 25-08-19 Fix a bug of non integer index/lob size when login.sql is active. | |
# 13-02-20 Excluded "ENABLE NOVALIDATE" from error log [After rebuild report] as it's not an actual error. | |
# 13-09-20 Correction of DBA_REDEFINITION_ERRORS query. | |
# 15-09-20 Added Rebuild Table to another Tablespace feature (available only for ALTER TABLE MOVE options). | |
# 16-09-20 Enhance the formatting of the outputs. | |
# 23-05-22 Using NULLIF(x,0) to workaround error "ORA-01476: divisor is equal to zero" when displaying table details post rebuild. | |
# ######################################################################################################################################################### | |
SCRIPT_NAME="rebuild_table" | |
# ########### | |
# VARIABLES: | |
# ########### | |
LIST_TOP_FRAG_TABS=Y # LIST TOP 50 FRAGMENTED TABLE EACH TIME SCRIPT RUN [Y/N] | |
CHECK_SPACE=Y # CHECK IF THE UNDERLYING TABLESPACE HAS SUFFICENT SPACE FOR THE REBUILD OPERATION [Y/N] | |
export LIST_TOP_FRAG_TABS | |
export CHECK_SPACE | |
# ########### | |
# Description: | |
# ########### | |
echo | |
echo "============================================" | |
echo "This script REBUILDS A TABLE and its INDEXES ..." | |
echo "============================================" | |
echo "" | |
echo "It will check first if the table can be REBUILD using DBMS_REDEIFINITION [Very Minimal Downtime will happen on the table]." | |
echo "It will check if ALTER TABLE MOVE ONLINE can be used for the rebuild, if you are on 12.2 or higher [Very Minimal Downtime will happen on the table]." | |
echo "If NO ONLINE TABLE REBUILD Options are available, it will use ALTER TABLE MOVE and rebuild its INDEXES. [A DOWNTIME will be mandatory on the table]" | |
echo "Lastly, You will be prompted to utilize options like Parallelism/Compression/Gather Statistics if they are available in your DB Edition." | |
echo "" | |
echo "Note: It's highly recommended to take a FULL DB BACKUP before the start of any table rebuild." | |
echo "Note: UNDO TABLESPACE and ARCHIVELOG LOCATION (or FRA) must be big enough to hold the data generated by the rebuild process." | |
echo | |
sleep 3 | |
# ####################################### | |
# Excluded INSTANCES: | |
# ####################################### | |
# Here you can mention the instances the script will IGNORE and will NOT run against: | |
# Use pipe "|" as a separator between each instance name. | |
# e.g. Excluding: -MGMTDB, ASM instances: | |
EXL_DB="\-MGMTDB|ASM|APX" #Excluded INSTANCES [Will not get reported offline]. | |
# ########################### | |
# Listing Available Databases: | |
# ########################### | |
# Count Instance Numbers: | |
INS_COUNT=$( ps -ef|grep pmon|grep -v grep|egrep -v ${EXL_DB}|wc -l ) | |
# Exit if No DBs are running: | |
if [ $INS_COUNT -eq 0 ] | |
then | |
echo "No Database is Running !" | |
echo | |
return | |
fi | |
# If there is ONLY one DB set it as default without prompt for selection: | |
if [ $INS_COUNT -eq 1 ] | |
then | |
export ORACLE_SID=$( ps -ef|grep pmon|grep -v grep|egrep -v ${EXL_DB}|awk '{print $NF}'|sed -e 's/ora_pmon_//g'|grep -v sed|grep -v "s///g" ) | |
# If there is more than one DB ASK the user to select: | |
elif [ $INS_COUNT -gt 1 ] | |
then | |
echo | |
echo "Select the ORACLE_SID:[Enter the number]" | |
echo "---------------------" | |
select DB_ID in $( ps -ef|grep pmon|grep -v grep|egrep -v ${EXL_DB}|awk '{print $NF}'|sed -e 's/ora_pmon_//g'|grep -v sed|grep -v "s///g" ) | |
do | |
integ='^[0-9]+$' | |
if ! [[ ${REPLY} =~ ${integ} ]] || [ ${REPLY} -gt ${INS_COUNT} ] || [ ${REPLY} -eq 0 ] | |
then | |
echo | |
echo "Error: Not a valid number!" | |
echo | |
echo "Enter a valid NUMBER from the displayed list !: i.e. Enter a number from [1 to ${INS_COUNT}]" | |
echo "----------------------------------------------" | |
else | |
export ORACLE_SID=$DB_ID | |
echo | |
printf "`echo "Selected Instance: ["` `echo -e "\033[33;5m${DB_ID}\033[0m"` `echo "]"`\n" | |
echo | |
break | |
fi | |
done | |
fi | |
# Exit if the user selected a Non Listed Number: | |
if [ -z "${ORACLE_SID}" ] | |
then | |
echo "You've Entered An INVALID ORACLE_SID" | |
exit | |
fi | |
# ######################### | |
# Getting ORACLE_HOME | |
# ######################### | |
ORA_USER=`ps -ef|grep ${ORACLE_SID}|grep pmon|grep -v grep|egrep -v ${EXL_DB}|awk '{print $1}'|tail -1` | |
USR_ORA_HOME=`grep ${ORA_USER} /etc/passwd| cut -f6 -d ':'|tail -1` | |
# SETTING ORATAB: | |
if [ -f /etc/oratab ] | |
then | |
ORATAB=/etc/oratab | |
export ORATAB | |
## If OS is Solaris: | |
elif [ -f /var/opt/oracle/oratab ] | |
then | |
ORATAB=/var/opt/oracle/oratab | |
export ORATAB | |
fi | |
# ATTEMPT1: Get ORACLE_HOME using pwdx command: | |
export PGREP=`which pgrep` | |
export PWDX=`which pwdx` | |
if [[ -x ${PGREP} ]] && [[ -x ${PWDX} ]] | |
then | |
PMON_PID=`pgrep -lf _pmon_${ORACLE_SID}|awk '{print $1}'` | |
export PMON_PID | |
ORACLE_HOME=`pwdx ${PMON_PID} 2>/dev/null|awk '{print $NF}'|sed -e 's/\/dbs//g'` | |
export ORACLE_HOME | |
fi | |
# ATTEMPT2: If ORACLE_HOME not found get it from oratab file: | |
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ] | |
then | |
## If OS is Linux: | |
if [ -f /etc/oratab ] | |
then | |
ORATAB=/etc/oratab | |
ORACLE_HOME=`grep -v '^\#' ${ORATAB} | grep -v '^$'| grep -i "^${ORACLE_SID}:" | perl -lpe'$_ = reverse' | cut -f3 | perl -lpe'$_ = reverse' |cut -f2 -d':'` | |
export ORACLE_HOME | |
## If OS is Solaris: | |
elif [ -f /var/opt/oracle/oratab ] | |
then | |
ORATAB=/var/opt/oracle/oratab | |
ORACLE_HOME=`grep -v '^\#' ${ORATAB} | grep -v '^$'| grep -i "^${ORACLE_SID}:" | perl -lpe'$_ = reverse' | cut -f3 | perl -lpe'$_ = reverse' |cut -f2 -d':'` | |
export ORACLE_HOME | |
fi | |
fi | |
# ATTEMPT3: If ORACLE_HOME is in /etc/oratab, use dbhome command: | |
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ] | |
then | |
ORACLE_HOME=`dbhome "${ORACLE_SID}"` | |
export ORACLE_HOME | |
fi | |
# ATTEMPT4: If ORACLE_HOME is still not found, search for the environment variable: [Less accurate] | |
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ] | |
then | |
ORACLE_HOME=`env|grep -i ORACLE_HOME|sed -e 's/ORACLE_HOME=//g'` | |
export ORACLE_HOME | |
fi | |
# ATTEMPT5: If ORACLE_HOME is not found in the environment search user's profile: [Less accurate] | |
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ] | |
then | |
ORACLE_HOME=`grep -h 'ORACLE_HOME=\/' ${USR_ORA_HOME}/.bash_profile ${USR_ORA_HOME}/.*profile | perl -lpe'$_ = reverse' |cut -f1 -d'=' | perl -lpe'$_ = reverse'|tail -1` | |
export ORACLE_HOME | |
fi | |
# ATTEMPT6: If ORACLE_HOME is still not found, search for orapipe: [Least accurate] | |
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ] | |
then | |
if [ -x /usr/bin/locate ] | |
then | |
ORACLE_HOME=`locate -i orapipe|head -1|sed -e 's/\/bin\/orapipe//g'` | |
export ORACLE_HOME | |
fi | |
fi | |
export LD_LIBRARY_PATH=${ORACLE_HOME}/lib | |
# ######################################## | |
# Exit if the user is not the Oracle Owner: | |
# ######################################## | |
CURR_USER=`whoami` | |
if [ ${ORA_USER} != ${CURR_USER} ]; then | |
echo "" | |
echo "You're Running This Sctipt with User: \"${CURR_USER}\" !!!" | |
echo "Please Run This Script With The Right OS User: \"${ORA_USER}\"" | |
echo "Script Terminated!" | |
exit | |
fi | |
# ##################### | |
# Getting DB Block Size: | |
# ##################### | |
VAL302=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off; | |
prompt | |
select value from v\$parameter where name='db_block_size'; | |
exit; | |
EOF | |
) | |
blksize=`echo ${VAL302}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
# ################### | |
# Checking DB Version: | |
# ################### | |
VAL311=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off; | |
prompt | |
select version from v\$instance; | |
exit; | |
EOF | |
) | |
DB_VER=`echo ${VAL311}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
DB_RELEASE=`echo ${VAL311}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f2 -d '.'` | |
CHK_IDX_ONLINE_OPTION_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off echo off; | |
SELECT count(*) from v\$option where parameter='Online Index Build' and value='TRUE'; | |
exit; | |
EOF | |
) | |
CHK_IDX_ONLINE_OPTION=`echo ${CHK_IDX_ONLINE_OPTION_RAW} | awk '{print $NF}'` | |
if [ ${CHK_IDX_ONLINE_OPTION} -eq 1 ] | |
then | |
export ONLINE_REBUILD="ONLINE" | |
fi | |
# ONLINE OPTION TO BE USED ON 12.2 and higher: | |
if [ ${DB_VER} -eq 12 ] | |
then | |
if [ ${DB_RELEASE} -gt 1 ] | |
then | |
if [ ${CHK_IDX_ONLINE_OPTION} -eq 1 ] | |
then | |
export ORACLE12_ONLINE="ONLINE UPDATE INDEXES" | |
export ORACLE12_HASH="--" | |
fi | |
fi | |
fi | |
if [ ${DB_VER} -gt 12 ] | |
then | |
if [ ${CHK_IDX_ONLINE_OPTION} -eq 1 ] | |
then | |
export ORACLE12_ONLINE="ONLINE UPDATE INDEXES" | |
export ORACLE12_HASH="--" | |
fi | |
fi | |
# ############################### | |
# Checking CDB Architecture: | |
# ############################### | |
# Check if the CBD Architecture is implemented if the DB Version is 12c or higher: | |
if [ ${DB_VER} -ge 12 ] | |
then | |
export ORACLE_PDB_SID="" | |
CDBACTIVERAW=$(${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
select count(*) from v\$containers where open_mode='READ WRITE'; | |
EOF | |
) | |
CDBACTIVE=`echo ${CDBACTIVERAW} | awk '{print $NF}'` | |
# If only one PDB found then set the ORACLE_PDB_SID variable to that PDB without the need to prompt the user: | |
if [ ${CDBACTIVE} -eq 2 ] | |
then | |
echo "" | |
echo "CBD Architecture detected!" | |
export ORACLE_PDB_SID="" | |
ORACLE_PDB_SID_RAW=$(${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
select name from v\$containers where name not in ('CDB\$ROOT','PDB\$SEED') and open_mode='READ WRITE'; | |
EOF | |
) | |
export ORACLE_PDB_SID=`echo ${ORACLE_PDB_SID_RAW} | awk '{print $NF}'` | |
export SET_CONTAINER="alter session set container = ${ORACLE_PDB_SID};" | |
echo "Setting ORACLE_PDB_SID to the only available PDB [${ORACLE_PDB_SID}]" | |
echo "" | |
fi | |
# If more than one PDB found then prompt the user to select from the PDBs list: | |
if [ ${CDBACTIVE} -gt 2 ] | |
then | |
echo "" | |
echo "CBD Architecture detected!" | |
export ORACLE_PDB_SID="" | |
PDB_COUNT_RAW=$(${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
set pages 0 feedback off echo off | |
select count(*) from v\$containers where name not in ('CDB\$ROOT','PDB\$SEED') and open_mode='READ WRITE'; | |
EOF | |
) | |
PDB_COUNT=`echo ${PDB_COUNT_RAW} | awk '{print $NF}'` | |
echo "" | |
echo "Select one PDB from the list:[Enter the number]" | |
echo "----------------------------" | |
echo "[For CDB Enter 0]" | |
echo | |
select PDB_DB_ID in $(${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
set pages 0 feedback off echo off | |
select name from v\$containers where name not in ('CDB\$ROOT','PDB\$SEED') and open_mode='READ WRITE'; | |
EOF | |
) | |
do | |
integ='^[1-9]+$' | |
# If input is 0 set the DB to CDB: | |
if [ ${REPLY} -eq 0 ] | |
then | |
export ORACLE_PDB_SID=""; export SET_CONTAINER="" | |
echo | |
echo "Setting CDB as default ..." | |
echo | |
fi | |
# For other input show PDB DBs: | |
if ! [[ ${REPLY} =~ ${integ} ]] || [ ${REPLY} -gt ${PDB_COUNT} ] || [ -z "${REPLY}" ] | |
then | |
echo | |
echo "Error: Not a valid number!" | |
echo | |
echo "Enter a valid NUMBER from the displayed list!: i.e. Enter a number from [1 to ${PDB_COUNT}]" | |
echo "---------------------------------------------" | |
else | |
export ORACLE_PDB_SID=${PDB_DB_ID}; export SET_CONTAINER="alter session set container = ${PDB_DB_ID};" | |
echo | |
printf "`echo "Selected PDB: ["` `echo -e "\033[33;5m${PDB_DB_ID}\033[0m"` `echo "]"`\n" | |
echo | |
break | |
fi | |
done | |
fi | |
fi | |
# ############################## | |
# LIST TOP 50 FRAGMENTED TABLES: | |
# ############################## | |
case ${LIST_TOP_FRAG_TABS} in | |
y|Y|yes|YES|Yes) | |
${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
set pages 1000 lines 169 feedback off | |
col owner for a30 | |
col table_name for a35 | |
col "%RECLAIMABLE_SPACE" for 99 | |
col "%FRAGMENTED_SPACE" for a17 | |
col LAST_ANALYZED for a13 | |
PROMPT | |
PROMPT LIST OF TOP FRAGMENTED TABLES ON THE DB: [The accuracy of this list depends on the existance of recent STATISTICS on tables] | |
PROMPT ---------------------------------------- | |
select * from (select owner,table_name,to_char(LAST_ANALYZED, 'DD-MON-YYYY') LAST_ANALYZED, | |
round(blocks * ${blksize}/1024/1024) "FULL_SIZE_MB", | |
round(num_rows * avg_row_len/1024/1024) "ACTUAL_SIZE_MB", | |
round(blocks * ${blksize}/1024/1024) - round(num_rows * avg_row_len/1024/1024) "FRAGMENTED_SPACE_MB", | |
round(((round((blocks * ${blksize}/1024/1024)) - round((num_rows * avg_row_len/1024/1024))) / round((blocks * ${blksize}/1024/1024))) * 100)||'%' "%FRAGMENTED_SPACE" | |
from dba_tables | |
where | |
owner <> 'SYS' | |
and blocks>10 | |
and round(blocks * ${blksize}/1024/1024) > 10 | |
-- List only the tables with Fragmented Space > 30%: | |
and ((round((blocks * ${blksize}/1024/1024)) - round((num_rows * avg_row_len/1024/1024))) / round((blocks * ${blksize}/1024/1024))) * 100 > 30 | |
order by "FRAGMENTED_SPACE_MB" desc) where rownum<51; | |
PROMPT | |
EOF | |
echo "";; | |
esac | |
# Checking FORCE LOGGING mode: | |
# ########################### | |
VAL1=$(${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
select force_logging from v\$database; | |
EOF | |
) | |
VAL2=`echo ${VAL1}| awk '{print $NF}'` | |
case ${VAL2} in | |
YES) echo | |
echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" | |
echo "INFO: THE DATABASE IS IN FORCE LOGGING MODE." | |
echo "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" | |
echo;sleep 2;; | |
*);; | |
esac | |
echo | |
echo "Enter the OWNER of The Table:" | |
echo "=============================" | |
while read OWNER | |
do | |
case ${OWNER} in | |
"")echo | |
echo "Enter the OWNER of the Table:" | |
echo "============================";; | |
*) | |
VAL11=$(${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
SELECT COUNT(*) FROM DBA_USERS WHERE USERNAME=upper('${OWNER}'); | |
EOF | |
) | |
VAL22=`echo ${VAL11}| awk '{print $NF}'` | |
case ${VAL22} in | |
0) echo;echo "ERROR: USER [${OWNER}] IS NOT EXIST ON DATABASE [${ORACLE_SID}] !" | |
echo; echo "Searching For Users Match The Provided String ..."; sleep 1 | |
${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
set linesize 143 | |
set pagesize 1000 | |
set feedback off | |
set trim on | |
set echo off | |
select username "Users Match Provided String" from dba_users where username like upper ('%${OWNER}%'); | |
EOF | |
echo;echo "Enter A Valid Table Owner:" | |
echo "=========================";; | |
*) break;; | |
esac | |
esac | |
done | |
echo | |
echo "Enter the TABLE Name:" | |
echo "====================" | |
while read OBJECT_NAME | |
do | |
case ${OBJECT_NAME} in | |
"")echo | |
echo "Enter the TABLE NAME:" | |
echo "====================";; | |
*) | |
VAL11=$(${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
SELECT COUNT(*) FROM DBA_TABLES WHERE OWNER=upper('${OWNER}') AND TABLE_NAME=UPPER('${OBJECT_NAME}'); | |
EOF | |
) | |
VAL22=`echo ${VAL11}| awk '{print $NF}'` | |
case ${VAL22} in | |
0) echo;echo "INFO: TABLE [${OBJECT_NAME}] IS NOT EXIST UNDER SCHEMA [${OWNER}] !" | |
echo;echo "Searching for tables match the provided string ..."; sleep 1 | |
${ORACLE_HOME}/bin/sqlplus -s '/ as sysdba' << EOF | |
set linesize 143 | |
set pagesize 1000 | |
set feedback off | |
set trim on | |
set echo off | |
select table_name "Tables Match Provided String:" from dba_tables where owner=upper('${OWNER}') and table_name like upper ('%${OBJECT_NAME}%'); | |
EOF | |
echo;echo "Enter A VALID TABLE NAME:" | |
echo "========================";; | |
*) break;; | |
esac | |
esac | |
done | |
VALLASTANALYZED=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select LAST_ANALYZED from DBA_TABLES where OWNER= upper('${OWNER}') and TABLE_NAME= upper('${OBJECT_NAME}'); | |
exit; | |
EOF | |
) | |
LASTANALYZED=`echo ${VALLASTANALYZED}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
VALTABUPDATES=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select UPDATES from DBA_TAB_MODIFICATIONS where TABLE_OWNER= upper('${OWNER}') and TABLE_NAME= upper('${OBJECT_NAME}'); | |
exit; | |
EOF | |
) | |
TABUPDATES=`echo ${VALTABUPDATES}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
# ################### | |
# Getting DB Version: | |
# ################### | |
VAL311=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off; | |
prompt | |
select version from v\$instance; | |
exit; | |
EOF | |
) | |
DB_VER=`echo ${VAL311}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
# ################### | |
# Getting TABLE SIZE: | |
# ################### | |
case ${CHECK_SPACE} in | |
y|Y|yes|YES|Yes) | |
echo "" | |
echo "[Calculating Table Size] ..." | |
# TABLE SIZE: | |
SINGLETABLESIZE_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select /*+RULE*/ ROUND(SUM(BYTES)/1024/1024) FROM DBA_SEGMENTS where owner=upper('${OWNER}') and SEGMENT_NAME=upper('${OBJECT_NAME}'); | |
exit; | |
EOF | |
) | |
export SINGLETABLESIZE=`echo ${SINGLETABLESIZE_RAW} |perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
# LOB SIZE: | |
LOBSIZE_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
SELECT /*+RULE*/ ROUND(SUM(BYTES)/1024/1024) FROM DBA_SEGMENTS WHERE SEGMENT_NAME IN | |
(SELECT /*+RULE*/ SEGMENT_NAME FROM DBA_LOBS WHERE owner=upper('${OWNER}') AND table_name=UPPER('${OBJECT_NAME}')); | |
exit; | |
EOF | |
) | |
export LOBSIZE=`echo ${LOBSIZE_RAW} |perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
# Zeriong an empty lob size: | |
if [ -z ${LOBSIZE} ] | |
then | |
export LOBSIZE=0 | |
fi | |
# Zeriong a non integer LOB size: | |
INT='^[0-9]+$' | |
if ! [[ ${LOBSIZE} =~ $INT ]] | |
then | |
export LOBSIZE=0 | |
fi | |
# INDEXES SIZE: | |
INDEXESSIZE_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
SELECT /*+RULE*/ round(SUM(BYTES/1024/1024)) FROM SYS.DBA_SEGMENTS WHERE OWNER = upper('${OWNER}') | |
AND SEGMENT_NAME in (select index_name from dba_indexes where owner=upper('${OWNER}') and table_name=UPPER('${OBJECT_NAME}')); | |
exit; | |
EOF | |
) | |
export INDEXESSIZE=`echo ${INDEXESSIZE_RAW} |perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
# Zeriong an empty index size: | |
if [ -z ${INDEXESSIZE} ] | |
then | |
export INDEXESSIZE=0 | |
fi | |
# Zeriong a non integer index size: | |
INT='^[0-9]+$' | |
if ! [[ $INDEXESSIZE =~ $INT ]] | |
then | |
export INDEXESSIZE=0 | |
fi | |
# TABLE + LOBS + INDEXES SIZE: | |
#export TABLESIZE=$(echo "${SINGLETABLESIZE} + ${LOBSIZE} + ${INDEXESSIZE}" | bc) | |
export TABLESIZE=$(awk "BEGIN {print ${SINGLETABLESIZE} + ${LOBSIZE} + ${INDEXESSIZE}}") | |
echo "[TABLE + INDEXES SIZE= ${TABLESIZE} MB]" | |
export SAFE_MARGIN="1.25" | |
#export TABLESIZEPLUSMARGIN=$(echo "${TABLESIZE} * ${SAFE_MARGIN}" | bc) | |
export TABLESIZEPLUSMARGIN=$(awk "BEGIN {print ${TABLESIZE} * ${SAFE_MARGIN}}") | |
# Convert TABLESIZEPLUSMARGIN from float number to integer: | |
export TABLESIZEPLUSMARGIN=${TABLESIZEPLUSMARGIN%.*} | |
# ########################################## | |
# Check the underlying TABLESPACE FREE SPACE: | |
# ########################################## | |
# Check the underlying tablespace: | |
UNDERLYINGTBS_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select tablespace_name from dba_tables where owner=upper('${OWNER}') and table_name=upper('${OBJECT_NAME}'); | |
prompt | |
exit; | |
EOF | |
) | |
UNDERLYINGTBS=`echo ${UNDERLYINGTBS_RAW} |perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
echo "" | |
echo "[Checking if [${UNDERLYINGTBS}] tablespace has SUFFICIENT FREE SPACE for this REBUILD operation] ..." | |
# Check the FREE SPACE on the underlying tablespace: | |
UNDERLYINGTBS_FREE_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select /*+RULE*/ round(((tablespace_size*${blksize})/(1024*1024)) - ((used_space*${blksize})/(1024*1024))) | |
from dba_tablespace_usage_metrics where tablespace_name=upper('${UNDERLYINGTBS}'); | |
prompt | |
exit; | |
EOF | |
) | |
UNDERLYINGTBS_FREE=`echo ${UNDERLYINGTBS_FREE_RAW} | awk '{print $NF}'` | |
# EXIT if the underlying tablespace FREE SPACE is less than TABLE SIZE + The SAFE MARGIN: | |
if [ ${UNDERLYINGTBS_FREE} -lt ${TABLESIZEPLUSMARGIN} ] | |
then | |
#REQUIREDSPACE=$(echo "${TABLESIZE} - ${UNDERLYINGTBS_FREE}" | bc) | |
REQUIREDSPACE=$(awk "BEGIN {print ${TABLESIZE} - ${UNDERLYINGTBS_FREE}}") | |
echo "" | |
echo -e "\033[33;5mThe underlying tablespace [${UNDERLYINGTBS}] has NO SUFFICIENT FREE SPACE to cater to this operation!\033[0m" | |
echo "TABLE + INDEXES SIZE= ${TABLESIZE} MB" | |
echo "TABLESPACE FREE SPACE= ${UNDERLYINGTBS_FREE} MB" | |
echo "You need to add at least ${REQUIREDSPACE} MB of extra space to [${UNDERLYINGTBS}] tablespace and then re-run the rebuild script again." | |
echo "If you think [${UNDERLYINGTBS}] tablespace has sufficient space and you want to skip this check, set the parameter CHECK_SPACE=N inside the script." | |
echo "" | |
echo "SCRIPT TERMINATED!" | |
echo "" | |
exit 1 | |
else | |
echo "[TABLESPACE FREE SPACE= ${UNDERLYINGTBS_FREE} MB]" | |
echo "" | |
echo "[Tablespace [${UNDERLYINGTBS}] has SUFFICIENT FREE SPACE.]" | |
fi | |
;; | |
esac | |
# ######################################################## | |
# Check if the supplement logging is enabled on the table: | |
# ######################################################## | |
CHECK_REPLICATION_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select count(*) from DBA_LOG_GROUPS where OWNER= upper('${OWNER}') and TABLE_NAME= upper('${OBJECT_NAME}'); | |
exit; | |
EOF | |
) | |
CHECK_REPLICATION=`echo ${CHECK_REPLICATION_RAW} | awk '{print $NF}'` | |
if [ ${CHECK_REPLICATION} -gt 0 ] | |
then | |
echo "" | |
echo -e "\033[33;5mWARNING WARNING WARNING!\033[0m" | |
echo "IS THIS TABLE IS GETTING REPLICATED TO ANOTHER DATABASE USING A REPLICATION TOOL i.e. Goldengate/Streams?" | |
echo "If this is the case; Then please Note that target table MAY miss some live data during the final SWAP step." | |
echo "Be in the safe side and execute the final SWAP command manually while the APPLICATION is DOWN." | |
echo "" | |
echo -e "\033[33;5m...\033[0m" | |
sleep 10 | |
fi | |
# #################### | |
# PARALLEL DEGREE: | |
# #################### | |
# Computing the default PARALLEL DEGREE based on CPU count: | |
case `uname` in | |
Linux ) export PARALLEL_DEGREE=`cat /proc/cpuinfo| grep processor|wc -l`;; | |
AIX ) export PARALLEL_DEGREE=`lsdev -C|grep Process|wc -l`;; | |
SunOS ) export PARALLEL_DEGREE=`kstat cpu_info|grep core_id|sort -u|wc -l`;; | |
HP-UX) export PARALLEL_DEGREE=`lsdev -C|grep Process|wc -l`;; | |
esac | |
if [ ! -z "${PARALLEL_DEGREE##[0-9]*}" ] | |
then | |
export PARALLEL_DEGREE=1 | |
fi | |
echo "" | |
echo "Number of CPUs detected on this machine is: ${PARALLEL_DEGREE}" | |
echo "" | |
echo "Enter the PARALLELISM DEGREE to be used for this rebuild operation? [Blank value means use the MAX CPU resources where PARALLELISM=${PARALLEL_DEGREE}]" | |
echo "===================================================================" | |
echo "[The HIGHER the PARALLELISM DEGREE the FASTER the REBUILD, but don't exceed the current number of CPUs [${PARALLEL_DEGREE}] on your system.]" | |
echo "[Note: 1 means NO Parallelism.]" | |
while read ENTERED_DEGREE | |
do | |
integ='^[0-9]+$' | |
case ${ENTERED_DEGREE} in | |
0) export ENTERED_DEGREE=1; break;; | |
"") export ENTERED_DEGREE=${PARALLEL_DEGREE};break;; | |
esac | |
if ! [[ ${ENTERED_DEGREE} =~ ${integ} ]] ; then | |
echo "Error: Not a valid number !" | |
echo | |
echo "Please Enter a VALID NUMBER for PARALLELISM DEGREE:" | |
echo "---------------------------------------------------" | |
else | |
export PARALLEL_DEGREE=${ENTERED_DEGREE} | |
echo "" | |
echo "DEGREE OF PARALLELISM IS SET TO [${ENTERED_DEGREE}]" | |
break | |
fi | |
done | |
# ########################################################## | |
# Check if the table can be REBUILD using DBMS_REDEFINITION: | |
# ########################################################## | |
echo "" | |
echo "[Checking if DBMS_REDEFINITION can be used to rebuild the table] ..." | |
CHK_ONLINE_REDEFINITION_OPTION_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off echo off; | |
SELECT count(*) from v\$option where parameter='Online Redefinition' and value='TRUE'; | |
exit; | |
EOF | |
) | |
CHK_ONLINE_REDEFINITION_OPTION=`echo ${CHK_ONLINE_REDEFINITION_OPTION_RAW} | awk '{print $NF}'` | |
if [ ${CHK_ONLINE_REDEFINITION_OPTION} -eq 1 ] | |
then | |
USEREDEFINITIONRAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 lines 1000; | |
prompt | |
EXEC DBMS_REDEFINITION.can_redef_table(upper('${OWNER}'),upper('${OBJECT_NAME}'),options_flag => DBMS_REDEFINITION.CONS_USE_ROWID); | |
exit; | |
EOF | |
) | |
USEREDEFINITION=`echo ${USEREDEFINITIONRAW}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
case ${USEREDEFINITIONRAW} in | |
*'currently being redefined'*) | |
echo "Looks you already ran the script against the same table and didn't complete." | |
echo -e "\033[33;5mPlease run the following command to CLEANUP the STATE of the previous execution then run rebuild_table script again:\033[0m" | |
echo "" | |
echo "EXEC DBMS_REDEFINITION.abort_redef_table(upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('<INTERIM_TABLE_NAME>'));" | |
echo "" | |
echo "SCRIPT TERMINATED!" | |
echo "" | |
exit 1;; | |
esac | |
case ${USEREDEFINITION} in | |
*completed*) | |
echo "" | |
echo -e "\033[33;5mVoila! TABLE [${OBJECT_NAME}] is eligible to be rebuild ONLINE using DBMS_REDEFINITION [with a Very Minimal Downtime on the table].\033[0m" | |
echo "" | |
echo "Do you want to use DBMS_REDEFINITION for ONLINE Table REBUILD with a MINIMAL DOWNTIME on the table? [Y|N] Y" | |
echo "===================================================================================================" | |
echo "Enter NO in case you want to use ALTER TABLE MOVE option." | |
while read ANS | |
do | |
case $ANS in | |
""|y|Y|yes|YES|Yes) | |
# Creating the INTERIM TABLE: | |
export OBJECT_NAME_INT=${OBJECT_NAME}_INT | |
# Check if the INTERIM TABLE is already exist: | |
INTERIM_TABLE_EXIST_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off echo off; | |
SELECT count(*) from dba_tables where owner=upper('${OWNER}') and table_name=upper('${OBJECT_NAME_INT}'); | |
exit; | |
EOF | |
) | |
INTERIM_TABLE_EXIST=`echo ${INTERIM_TABLE_EXIST_RAW} | awk '{print $NF}'` | |
if [ ${INTERIM_TABLE_EXIST} -eq 1 ] | |
then | |
echo -e "\033[33;5mThe INTERIM table [${OWNER}.${OBJECT_NAME_INT}] IS ALREADY EXIST!\033[0m" | |
echo "Changing the INTERIM TABLE NAME to [${OBJECT_NAME}_XNT]." | |
export OBJECT_NAME_INT=${OBJECT_NAME}_XNT | |
# Second Attempt of checking the existance of INTERIM table: | |
INTERIM_TABLE_EXIST2_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off echo off; | |
SELECT count(*) from dba_tables where owner=upper('${OWNER}') and table_name=upper('${OBJECT_NAME_INT}'); | |
exit; | |
EOF | |
) | |
INTERIM_TABLE_EXIST2=`echo ${INTERIM_TABLE_EXIST2_RAW} | awk '{print $NF}'` | |
if [ ${INTERIM_TABLE_EXIST2} -eq 1 ] | |
then | |
echo -e "\033[33;5mAgain! A table with same name of the INTERIM table [${OBJECT_NAME_INT}] IS ALREADY EXIST!\033[0m" | |
echo "Most probably you ran this script multiple times against the same table, if this is the case; then please DROP the old INTERIM tables|MATERIALIZED VIEWS." | |
echo "SCRIPT TERMINATED!" | |
echo "" | |
exit 1 | |
fi | |
fi | |
# SETTING PCT_FREE FOR THE TABLE AFTER THE REBUILD: | |
# ################################################# | |
VALDEFAULTPCTFREE=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select PCT_FREE from DBA_TABLES where owner=upper('${OWNER}') and table_name=upper('${OBJECT_NAME}'); | |
exit; | |
EOF | |
) | |
DEFAULTPCTFREE=`echo ${VALDEFAULTPCTFREE}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
echo "" | |
echo "INFO: Current PCTFREE: ${DEFAULTPCTFREE}" | |
echo "INFO: Number of \"UPDATE\" transactions on the table since the last Statistics Gathered on [${LASTANALYZED}]: ${TABUPDATES}" | |
echo | |
echo | |
echo "Specify the table PCTFREE after the rebuild: [How much %Free space will be left in each block for future updates | Current ${DEFAULTPCTFREE}%]" | |
echo "===========================================" | |
echo "Note: The SMALLER the PCTFREE the SMALLER the table size after the rebuild. [Recommended for Archival/Datawarehouse Tables]" | |
echo "Note: If the table is highly updated it's recommended to keep the current PCTFREE: ${DEFAULTPCTFREE}" | |
echo "Leave it BLANK and hit Enter to keep the default PCTFREE." | |
while read TABPCTFREEVAL | |
do | |
case ${TABPCTFREEVAL} in | |
"") export TABPCTFREE=${DEFAULTPCTFREE} | |
break;; | |
*[!0-9]*) echo "Please enter a valid NUMBER for PCTFREE:";; | |
*) export TABPCTFREE=${TABPCTFREEVAL} | |
break;; | |
esac | |
done | |
# INTERIM TABLE CREATION: | |
INTERIMTABLECREATIONRAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 lines 1000; | |
prompt | |
CREATE TABLE ${OWNER}.${OBJECT_NAME_INT} PCTFREE ${TABPCTFREE} AS SELECT * FROM ${OWNER}.${OBJECT_NAME} WHERE 1=2; | |
exit; | |
EOF | |
) | |
INTERIMTABLECREATION=`echo ${INTERIMTABLECREATIONRAW}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
case ${INTERIMTABLECREATION} in | |
*created*) | |
echo "The INTERIM table [${OBJECT_NAME_INT}] created successfully." | |
echo "" | |
echo "Do you want to run the FINAL step of SWAPPING to the new table MANUALLY? [Where the minimal DOWNTIME will occur] [Y|N] Y" | |
echo "=======================================================================" | |
echo "Enter [NO] to let the script run all the steps AUTOMATICALLY for you." | |
while read MANUALRUN | |
do | |
case $MANUALRUN in | |
""|y|Y|yes|YES|Yes)export HASHNOTIFY="";export HASHSWAP="--";export HASHSTATS="--"; break;; | |
n|N|no|NO|No) export HASHNOTIFY="--";export HASHSWAP="";export HASHSTATS="" | |
echo "" | |
echo "Do you want to GATHER NEW STATISTICS after table rebuild [Recommended]? [Y|N] Y" | |
echo "======================================================================" | |
echo "Enter NO to keep the old statistics after the rebuild." | |
while read ANS2 | |
do | |
case $ANS2 in | |
""|y|Y|yes|YES|Yes) export HASHSTATS=""; break;; | |
n|N|no|NO|No) export HASHSTATS="--"; break;; | |
*) echo "Please enter a VALID answer [Y|N]" ;; | |
esac | |
done | |
break;; | |
*) echo "Please enter a VALID answer [Y|N]" ;; | |
esac | |
done | |
# Creating the REBUILD script: | |
if [ ! -d ${USR_ORA_HOME} ] | |
then | |
export USR_ORA_HOME=/tmp | |
fi | |
REBUILDTABLESCRIPT=${USR_ORA_HOME}/REBUILDTABLESCRIPT-${OWNER}.${OBJECT_NAME}.sql | |
REBUILDTABLESCRIPTRUNNER=${USR_ORA_HOME}/REBUILDTABLESCRIPT-${OWNER}.${OBJECT_NAME}.sh | |
REBUILDTABLESPOOL=${USR_ORA_HOME}/REBUILDTABLESCRIPT-${OWNER}.${OBJECT_NAME}.log | |
echo "spool ${REBUILDTABLESPOOL}" > ${REBUILDTABLESCRIPT} | |
echo "PROMPT THIS OPERATION IS LOGGED IN: [${REBUILDTABLESPOOL}]" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "set pages 0 feedback off lines 168" >> ${REBUILDTABLESCRIPT} | |
echo "EXEC DBMS_SESSION.set_identifier('REBUILDING_${OWNER}.${OBJECT_NAME}');" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ***************" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT Session Details:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ***************" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "select 'OSPID: '||p.spid from v\$session s, v\$process p where s.sid=(select sid from v\$mystat where rownum=1) and s.paddr=p.addr;" >> ${REBUILDTABLESCRIPT} | |
echo "select 'SID: '||sid from v\$mystat where rownum = 1;" >> ${REBUILDTABLESCRIPT} | |
echo "select 'Serial#: '||s.serial# from v\$session s where s.sid = (select sid from v\$mystat where rownum = 1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT You can KILL this session using this command:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ********************************************" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "select 'ALTER SYSTEM DISCONNECT SESSION '''||sid||','||serial#||''' IMMEDIATE;' from v\$session where sid = (select sid from v\$mystat where rownum = 1);" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT TABLE INFO BEFORE THE REBUILD:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT *****************************" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "set linesize 168 pages 1000 heading on feedback on" >> ${REBUILDTABLESCRIPT} | |
echo "col \"OWNER.TABLE\" for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col tablespace_name for a20" >> ${REBUILDTABLESCRIPT} | |
echo "col \"READONLY\" for a8" >> ${REBUILDTABLESCRIPT} | |
echo "col \"%RECLAIM\" for 999" >> ${REBUILDTABLESCRIPT} | |
echo "col LAST_ANALYZED for a13" >> ${REBUILDTABLESCRIPT} | |
echo "col COMPRESSION for a8" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "select /*+RULE*/ t.owner||'.'||t.table_name \"OWNER.TABLE\",t.TABLESPACE_NAME,d.extents,t.LOGGING" >> ${REBUILDTABLESCRIPT} | |
echo ",t.COMPRESSION,t.READ_ONLY \"READONLY\",o.created,to_char(t.LAST_ANALYZED, 'DD-MON-YYYY') LAST_ANALYZED" >> ${REBUILDTABLESCRIPT} | |
echo ",round(d.bytes/1025/1024) SIZE_MB," >> ${REBUILDTABLESCRIPT} | |
echo "round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * t.avg_row_len/1024/1024), 2) \"FRAGMENTED_SPACE_MB\"," >> ${REBUILDTABLESCRIPT} | |
echo "((round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * t.avg_row_len/1024/1024), 2)) /" >> ${REBUILDTABLESCRIPT} | |
echo "round((t.blocks * ${blksize}/1024/1024), 2)) * 100 \"%RECLAIM\"" >> ${REBUILDTABLESCRIPT} | |
echo "from dba_tables t, dba_objects o, dba_segments d" >> ${REBUILDTABLESCRIPT} | |
echo "where t.owner= upper('${OWNER}')" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name = upper('${OBJECT_NAME}')" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=t.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and o.object_name=t.table_name" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=d.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name=d.SEGMENT_NAME;" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT LOBS:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT -----" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "col COMPRESSION for a8" >> ${REBUILDTABLESCRIPT} | |
echo "col SEGMENT_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col INDEX_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col SECUREFILE for a10" >> ${REBUILDTABLESCRIPT} | |
echo "col COLUMN_NAME for a40" >> ${REBUILDTABLESCRIPT} | |
echo "select SEGMENT_NAME,COLUMN_NAME,TABLESPACE_NAME,INDEX_NAME,SECUREFILE,COMPRESSION from dba_lobs" >> ${REBUILDTABLESCRIPT} | |
echo "where owner=upper('${OWNER}') and table_name = upper('${OBJECT_NAME}');" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT INDEXES BEFORE THE REBUILD:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ---------------------------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN OWNER FORMAT A25 heading \"Index Owner\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN INDEX_NAME FORMAT A30 heading \"Index Name\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN COLUMN_NAME FORMAT A25 heading \"On Column\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN COLUMN_POSITION FORMAT 9999 heading \"Pos\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN \"INDEX\" FORMAT A35" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN INDEX_TYPE FOR A16" >> ${REBUILDTABLESCRIPT} | |
echo "SELECT /*+RULE*/ IND.OWNER||'.'||IND.INDEX_NAME \"INDEX\"," >> ${REBUILDTABLESCRIPT} | |
echo " IND.INDEX_TYPE," >> ${REBUILDTABLESCRIPT} | |
echo " COL.COLUMN_NAME," >> ${REBUILDTABLESCRIPT} | |
echo " COL.COLUMN_POSITION," >> ${REBUILDTABLESCRIPT} | |
echo " IND.TABLESPACE_NAME," >> ${REBUILDTABLESCRIPT} | |
echo " IND.STATUS," >> ${REBUILDTABLESCRIPT} | |
echo " IND.UNIQUENESS," >> ${REBUILDTABLESCRIPT} | |
echo " IND.LAST_ANALYZED,round(d.bytes/1024/1024) SIZE_MB" >> ${REBUILDTABLESCRIPT} | |
echo "FROM SYS.DBA_INDEXES IND," >> ${REBUILDTABLESCRIPT} | |
echo " SYS.DBA_IND_COLUMNS COL," >> ${REBUILDTABLESCRIPT} | |
echo " DBA_SEGMENTS d" >> ${REBUILDTABLESCRIPT} | |
echo "WHERE IND.TABLE_NAME = upper('${OBJECT_NAME}')" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.TABLE_OWNER = upper('${OWNER}')" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.TABLE_NAME = COL.TABLE_NAME" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.OWNER = d.OWNER(+)" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.OWNER = COL.INDEX_OWNER" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.TABLE_OWNER = COL.TABLE_OWNER" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.INDEX_NAME = COL.INDEX_NAME" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.INDEX_NAME = d.SEGMENT_NAME(+);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT CONSTRAINTS BEFORE THE REBUILD:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT -------------------------------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "col CONSTRAINT_NAME for a30" >> ${REBUILDTABLESCRIPT} | |
echo "col R_CONSTRAINT_NAME for a30" >> ${REBUILDTABLESCRIPT} | |
echo "select CONSTRAINT_NAME,CONSTRAINT_TYPE,R_CONSTRAINT_NAME,STATUS,DEFERRED,INDEX_NAME from dba_constraints where">> ${REBUILDTABLESCRIPT} | |
echo "OWNER=upper('${OWNER}') and TABLE_NAME=upper('${OBJECT_NAME}') order by CONSTRAINT_TYPE;" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [Setting the PARALLELISM FACTOR to ${PARALLEL_DEGREE}] ..." >> ${REBUILDTABLESCRIPT} | |
echo "alter session enable parallel dml;" >> ${REBUILDTABLESCRIPT} | |
echo "alter session enable parallel ddl;" >> ${REBUILDTABLESCRIPT} | |
echo "alter session enable parallel query;" >> ${REBUILDTABLESCRIPT} | |
echo "alter session force parallel dml parallel ${PARALLEL_DEGREE};" >> ${REBUILDTABLESCRIPT} | |
echo "alter session force parallel ddl parallel ${PARALLEL_DEGREE};" >> ${REBUILDTABLESCRIPT} | |
echo "alter session force parallel query parallel ${PARALLEL_DEGREE};" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [Setting the SESSION DDL WAIT FOR LOCK to 5 minutes] ..." >> ${REBUILDTABLESCRIPT} | |
echo "alter session set ddl_lock_timeout=300;" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [Setting the SESSION RESUMABLE TIMEOUT to 6 Hours] ..." >> ${REBUILDTABLESCRIPT} | |
echo "ALTER SESSION ENABLE RESUMABLE TIMEOUT 21600 NAME 'REBUILD_OF_TABLE_${OBJECT_NAME}';" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [Starting REBUILDING the table using DBMS_REDEFINITION] ..." >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT At anytime you can abort the REBUILD process by executing this command:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ----------------------------------------------------------------------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT exec dbms_redefinition.abort_redef_table(upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}'));;" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT REBUILDING TABLE PROCEDURE WILL START WITHIN 5 Seconds ..." >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT -------------------------------------------------------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "SET FEEDBACK OFF" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(4);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [5]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [4]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [3]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [2]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [1]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "SET FEEDBACK ON" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT Keep checking the progress using this statement:" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT ------------------------------------------------" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col OPERATION for a21" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col \"%DONE\" for 999.999" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col \"STARTED|MIN_ELAPSED|REMAIN\" for a26" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col MESSAGE for a90" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col \"USERNAME| SID,SERIAL#\" for a28" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT select USERNAME||'| '||SID||','||SERIAL# \"USERNAME| SID,SERIAL#\",SQL_ID,round(SOFAR/TOTALWORK*100,2) \"%DONE\"" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT ,to_char(START_TIME,'DD-Mon HH24:MI')||'| '||trunc(ELAPSED_SECONDS/60)||'|'||trunc(TIME_REMAINING/60) \"STARTED|MIN_ELAPSED|REMAIN\" ,MESSAGE" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT from v\$session_longops" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT where TARGET LIKE UPPER('%${OBJECT_NAME}%') and TOTALWORK <> '0' and SOFAR/TOTALWORK*100 <>'100'" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT order by \"STARTED|MIN_ELAPSED|REMAIN\" desc, \"USERNAME| SID,SERIAL#\";;" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "--Exit the script if any failure encountered at any stage:" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "set serveroutput on" >>${REBUILDTABLESCRIPT} | |
echo "WHENEVER SQLERROR EXIT SQL.SQLCODE;" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT START DUPLICATING THE TABLE TO [${OBJECT_NAME_INT}]: [The execution time is dependant on the size of the table and its indexes]" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT ---------------------------------------------------------" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT EXEC DBMS_REDEFINITION.start_redef_table(upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}'),options_flag => DBMS_REDEFINITION.CONS_USE_ROWID);;" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} PROMPT [AN ORA-NOTIFICATION MESSAGE WILL BE WRITTEN TO THE ALERTLOG ONEC THE REBUILD OPERATION IS COMPLETED.]" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT NOTE: Feel free to exit from this session as the script is running in the BACKGROUND." >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "SET TIMING ON" >>${REBUILDTABLESCRIPT} | |
echo "EXEC DBMS_REDEFINITION.start_redef_table(upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}'),options_flag => DBMS_REDEFINITION.CONS_USE_ROWID);" >>${REBUILDTABLESCRIPT} | |
echo "SET TIMING OFF" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT [INTERIM TABLE INITIAL COPY COMPLETED.]" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT Creating Dependant Objects [Including Indexes] ..." >>${REBUILDTABLESCRIPT} | |
echo "PROMPT ----------------------------------------------" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT DECLARE" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT num_errors PLS_INTEGER;;" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT BEGIN" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS (upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}')," >>${REBUILDTABLESCRIPT} | |
echo "PROMPT DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors, TRUE);;" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT END;;" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT /" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "SET TIMING ON" >>${REBUILDTABLESCRIPT} | |
echo "DECLARE" >>${REBUILDTABLESCRIPT} | |
echo "num_errors PLS_INTEGER;" >>${REBUILDTABLESCRIPT} | |
echo "BEGIN" >>${REBUILDTABLESCRIPT} | |
echo "DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS (upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}')," >>${REBUILDTABLESCRIPT} | |
echo "DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors, TRUE);" >>${REBUILDTABLESCRIPT} | |
echo "END;" >>${REBUILDTABLESCRIPT} | |
echo "/" >>${REBUILDTABLESCRIPT} | |
echo "SET TIMING OFF" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT [DEPENDANT OBJECTS CREATED.]" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT [Checking the ERROR Log:]" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT SELECT OBJECT_NAME,DDL_TEXT FROM DBA_REDEFINITION_ERRORS WHERE BASE_TABLE_NAME=UPPER('${OBJECT_NAME}');;" >>${REBUILDTABLESCRIPT} | |
echo "set long 200" >>${REBUILDTABLESCRIPT} | |
echo "col DDL_TXT for a150" >>${REBUILDTABLESCRIPT} | |
echo "select object_name, ddl_txt from DBA_REDEFINITION_ERRORS where base_table_name=upper('${OBJECT_NAME}') and ddl_txt not like '%NULL ENABLE NOVALIDATE%';" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT Running the FINAL SYNC of the INTERIM TABLE Before the Actual SWAP:" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT ------------------------------------------------------------------">>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT EXEC DBMS_REDEFINITION.sync_interim_table(upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}'));;">>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "SET TIMING ON" >>${REBUILDTABLESCRIPT} | |
echo "EXEC DBMS_REDEFINITION.sync_interim_table(upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}'));" >>${REBUILDTABLESCRIPT} | |
echo "SET TIMING OFF" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT Running a COMPARISON between the OLD and NEW TABLE:" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT ***************************************************" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT TABLES:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "set linesize 168 pages 1000 heading on feedback off" >> ${REBUILDTABLESCRIPT} | |
echo "col \"TABLE_NAME\" for a55" >> ${REBUILDTABLESCRIPT} | |
echo "col COMPRESSION for a8" >> ${REBUILDTABLESCRIPT} | |
echo "col tablespace_name for a20" >> ${REBUILDTABLESCRIPT} | |
echo "col \"READONLY\" for a8" >> ${REBUILDTABLESCRIPT} | |
echo "col DEGREE for a7" >> ${REBUILDTABLESCRIPT} | |
echo "col \"%RECLAIM\" for 999" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN TABLE_NAME FORMAT A40 heading \"Table Name\"" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "select /*+RULE*/ 'ORIGINAL_TABLE: '||t.table_name \"TABLE_NAME\",t.TABLESPACE_NAME,d.extents," >> ${REBUILDTABLESCRIPT} | |
echo "t.COMPRESSION,t.READ_ONLY \"READONLY\"" >> ${REBUILDTABLESCRIPT} | |
echo ",round(d.bytes/1025/1024) SIZE_MB," >> ${REBUILDTABLESCRIPT} | |
echo "round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * t.avg_row_len/1024/1024), 2) \"FRAGMENTED_SPACE_MB\"," >> ${REBUILDTABLESCRIPT} | |
echo "((round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * t.avg_row_len/1024/1024), 2)) /" >> ${REBUILDTABLESCRIPT} | |
echo "round((t.blocks * ${blksize}/1024/1024), 2)) * 100 \"%RECLAIM\"" >> ${REBUILDTABLESCRIPT} | |
echo "from dba_tables t, dba_objects o, dba_segments d" >> ${REBUILDTABLESCRIPT} | |
echo "where t.owner= upper('${OWNER}')" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name = upper('${OBJECT_NAME}')" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=t.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and o.object_name=t.table_name" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=d.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name=d.SEGMENT_NAME" >> ${REBUILDTABLESCRIPT} | |
echo "union" >> ${REBUILDTABLESCRIPT} | |
echo "select /*+RULE*/ 'NEW_TABLE: '||t.table_name TABLE_NAME,t.TABLESPACE_NAME,d.extents" >> ${REBUILDTABLESCRIPT} | |
echo ",t.COMPRESSION,t.READ_ONLY \"READONLY\"" >> ${REBUILDTABLESCRIPT} | |
echo ",round(d.bytes/1025/1024) SIZE_MB" >> ${REBUILDTABLESCRIPT} | |
echo ",round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * t.avg_row_len/1024/1024), 2) \"FRAGMENTED_SPACE_MB\"" >> ${REBUILDTABLESCRIPT} | |
echo ",((round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * nullif(t.avg_row_len,0)/1024/1024), 2)) /" >> ${REBUILDTABLESCRIPT} | |
echo "round((t.blocks * ${blksize}/1024/1024), 2)) * 100 \"%RECLAIM\"" >> ${REBUILDTABLESCRIPT} | |
echo "from dba_tables t, dba_objects o, dba_segments d" >> ${REBUILDTABLESCRIPT} | |
echo "where t.owner= upper('${OWNER}')" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name = upper('${OBJECT_NAME_INT}')" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=t.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and o.object_name=t.table_name" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=d.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name=d.SEGMENT_NAME" >> ${REBUILDTABLESCRIPT} | |
echo "order by 1 desc;" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "set pages 0" >> ${REBUILDTABLESCRIPT} | |
echo "select 'ORIGINAL_TABLE NUMBER OF ROWS: '||count(*) from ${OWNER}.${OBJECT_NAME};" >> ${REBUILDTABLESCRIPT} | |
echo "select 'NEW_TABLE NUMBER OF ROWS: '||count(*) from ${OWNER}.${OBJECT_NAME_INT};" >> ${REBUILDTABLESCRIPT} | |
echo "set pages 1000" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT LOBS:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT -----" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "col SEGMENT_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col INDEX_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col COMPRESSION for a8" >> ${REBUILDTABLESCRIPT} | |
echo "col SECUREFILE for a10" >> ${REBUILDTABLESCRIPT} | |
echo "col COLUMN_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "select 'ORIGINAL_TABLE: '||TABLE_NAME,SEGMENT_NAME,COLUMN_NAME,TABLESPACE_NAME,INDEX_NAME,SECUREFILE,COMPRESSION from dba_lobs" >> ${REBUILDTABLESCRIPT} | |
echo "where owner=upper('${OWNER}') and table_name = upper('${OBJECT_NAME}')" >> ${REBUILDTABLESCRIPT} | |
echo "union" >> ${REBUILDTABLESCRIPT} | |
echo "select 'NEW_TABLE: '||TABLE_NAME,SEGMENT_NAME,COLUMN_NAME,TABLESPACE_NAME,INDEX_NAME,SECUREFILE,COMPRESSION from dba_lobs" >> ${REBUILDTABLESCRIPT} | |
echo "where owner=upper('${OWNER}') and table_name = upper('${OBJECT_NAME_INT}');" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT INDEXES:" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT --------" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "COLUMN TABLE_NAME FORMAT A45 heading \"Table Name\"" >>${REBUILDTABLESCRIPT} | |
echo "COLUMN INDEX_NAME FORMAT A30 heading \"Index Name\"" >>${REBUILDTABLESCRIPT} | |
echo "COLUMN COLUMN_NAME FORMAT A25 heading \"On Column\"" >>${REBUILDTABLESCRIPT} | |
echo "COLUMN COLUMN_POSITION FORMAT 9999 heading \"Pos\"" >>${REBUILDTABLESCRIPT} | |
echo "COLUMN \"INDEX\"FORMAT A35" >>${REBUILDTABLESCRIPT} | |
echo "COLUMN TABLESPACE_NAME FOR A25" >>${REBUILDTABLESCRIPT} | |
echo "COLUMN INDEX_TYPE FOR A14" >>${REBUILDTABLESCRIPT} | |
echo "SELECT /*+RULE*/ 'ORIGINAL_TABLE: '||I.TABLE_NAME \"TABLE_NAME\", I.INDEX_NAME \"INDEX\",I.STATUS,I.INDEX_TYPE,C.COLUMN_NAME,C.COLUMN_POSITION," >>${REBUILDTABLESCRIPT} | |
echo "I.UNIQUENESS \"UNIQUE\",round(d.bytes/1024/1024) SIZE_MB FROM DBA_INDEXES I, DBA_IND_COLUMNS C, DBA_SEGMENTS d" >>${REBUILDTABLESCRIPT} | |
echo "WHERE I.TABLE_NAME = upper('${OBJECT_NAME}') AND I.TABLE_OWNER = upper('${OWNER}') AND I.TABLE_NAME = C.TABLE_NAME" >>${REBUILDTABLESCRIPT} | |
echo "AND I.OWNER = d.OWNER AND I.OWNER = C.INDEX_OWNER AND I.TABLE_OWNER = C.TABLE_OWNER AND I.INDEX_NAME = C.INDEX_NAME" >>${REBUILDTABLESCRIPT} | |
echo "AND I.INDEX_NAME = d.SEGMENT_NAME" >>${REBUILDTABLESCRIPT} | |
echo "union" >>${REBUILDTABLESCRIPT} | |
echo "SELECT 'NEW_TABLE: '||I.TABLE_NAME \"TABLE_NAME\", I.INDEX_NAME \"INDEX\",I.STATUS,I.INDEX_TYPE,C.COLUMN_NAME,C.COLUMN_POSITION," >>${REBUILDTABLESCRIPT} | |
echo "I.UNIQUENESS \"UNIQUE\",round(d.bytes/1024/1024) SIZE_MB FROM DBA_INDEXES I, DBA_IND_COLUMNS C, DBA_SEGMENTS d" >>${REBUILDTABLESCRIPT} | |
echo "WHERE I.TABLE_NAME = upper('${OBJECT_NAME_INT}') AND I.TABLE_OWNER = upper('${OWNER}') AND I.TABLE_NAME = C.TABLE_NAME" >>${REBUILDTABLESCRIPT} | |
echo "AND I.OWNER = d.OWNER AND I.OWNER = C.INDEX_OWNER AND I.TABLE_OWNER = C.TABLE_OWNER AND I.INDEX_NAME = C.INDEX_NAME" >>${REBUILDTABLESCRIPT} | |
echo "AND I.INDEX_NAME = d.SEGMENT_NAME AND COLUMN_NAME <> 'M_ROW\$\$'" >>${REBUILDTABLESCRIPT} | |
echo "order by 1 desc;" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT Dependant Objects:" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT ------------------" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "select 'ORIGINAL_TABLE: '||NAME \"TABLE_NAME\",REFERENCED_OWNER,REFERENCED_NAME,REFERENCED_TYPE from DBA_DEPENDENCIES where">>${REBUILDTABLESCRIPT} | |
echo "OWNER=upper('${OWNER}') and NAME=upper('${OBJECT_NAME_INT}')" >>${REBUILDTABLESCRIPT} | |
echo "union" >>${REBUILDTABLESCRIPT} | |
echo "select 'NEW_TABLE: '||NAME \"TABLE_NAME\",REFERENCED_OWNER,REFERENCED_NAME,REFERENCED_TYPE from DBA_DEPENDENCIES where">>${REBUILDTABLESCRIPT} | |
echo "OWNER=upper('${OWNER}') and NAME=upper('${OBJECT_NAME}')" >>${REBUILDTABLESCRIPT} | |
echo "order by 1 desc;" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT CONSTRAINTS:" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT ------------" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "col CONSTRAINT_NAME for a30" >> ${REBUILDTABLESCRIPT} | |
echo "col R_CONSTRAINT_NAME for a30" >> ${REBUILDTABLESCRIPT} | |
echo "select 'ORIGINAL_TABLE: '||TABLE_NAME \"TABLE_NAME\",CONSTRAINT_NAME,CONSTRAINT_TYPE,R_CONSTRAINT_NAME,STATUS,DEFERRED,INDEX_NAME from dba_constraints where">>${REBUILDTABLESCRIPT} | |
echo "OWNER=upper('${OWNER}') and TABLE_NAME=upper('${OBJECT_NAME_INT}')" >>${REBUILDTABLESCRIPT} | |
echo "union" >>${REBUILDTABLESCRIPT} | |
echo "select 'NEW_TABLE: '||TABLE_NAME \"TABLE_NAME\",CONSTRAINT_NAME,CONSTRAINT_TYPE,R_CONSTRAINT_NAME,STATUS,DEFERRED,INDEX_NAME from dba_constraints where">>${REBUILDTABLESCRIPT} | |
echo "OWNER=upper('${OWNER}') and TABLE_NAME=upper('${OBJECT_NAME}')" >>${REBUILDTABLESCRIPT} | |
echo "order by 1 desc,CONSTRAINT_TYPE;" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT [Checking the ERROR Log ...]" >>${REBUILDTABLESCRIPT} | |
echo "select object_name, ddl_txt from DBA_REDEFINITION_ERRORS where base_table_name=upper('${OBJECT_NAME}');" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} PROMPT ***********************" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} PROMPT Running the ACTUAL SWAP [FINAL STAGE]:" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} PROMPT ***********************" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} PROMPT [AN ORA-NOTIFICATION MESSAGE WILL BE WRITTEN TO THE ALERTLOG ONEC THE SWAP IS COMPLETED.]" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} PROMPT EXEC DBMS_REDEFINITION.finish_redef_table(upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}'));;">>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} SET TIMING ON" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} EXEC DBMS_REDEFINITION.finish_redef_table(upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}'));" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} SET TIMING OFF" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} SET FEEDBACK OFF" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} exec dbms_system.ksdwrt(3,'ORA-NOTIFICATION: THE REBUILD OF TABLE [${OWNER}.${OBJECT_NAME}] USING DBMS_REDEFINITION COMPLETED.');">>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} SET FEEDBACK On" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} PROMPT [THE SWAP BETWEEN THE INTERIM AND ACTUAL TABLE IS COMPLETED.]" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSWAP} exec dbms_system.ksdwrt(3,'ORA-NOTIFICATION: ALL REBUILD STEPS OF TABLE [${OWNER}.${OBJECT_NAME}] COMPLETED. PLEASE CHECK THE LOGFILE: [${REBUILDTABLESPOOL}]');" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT ALL REBUILD STEPS ARE COMPLETED EXCEPT THE ACTUAL SWAP BETWEEN THE ORIGINAL AND INTERIM TABLE." >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT **************************************************" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT EXECUTE THE FOLLOWING ACTUAL SWAP COMMAND MANUALLY: [Minimal DOWNTIME will happen]" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT **************************************************" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT EXEC DBMS_REDEFINITION.finish_redef_table(upper('${OWNER}'), upper('${OBJECT_NAME}'), upper('${OBJECT_NAME_INT}'));;">>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} exec dbms_system.ksdwrt(3,'ORA-NOTIFICATION: ALL PRE-STEPS OF REBUILDING TABLE [${OWNER}.${OBJECT_NAME}] ARE COMPLETED PLEASE RUN THE FINAL SWAP COMMAND ASAP TO FINALISE THE REBUILD OPERATION: EXEC DBMS_REDEFINITION.finish_redef_table(upper(''${OWNER}''), upper(''${OBJECT_NAME}''), upper(''${OBJECT_NAME_INT}''));');" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT [Note: It's recommended to GATHER NEW STATISTICS on the table after the execution of the above SWAP command.]">>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT BEGIN" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT DBMS_STATS.GATHER_TABLE_STATS (" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT ownname => upper('${OWNER}')," >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT TABNAME => upper('${OBJECT_NAME}')," >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT DEGREE => DBMS_STATS.AUTO_DEGREE," >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT CASCADE => TRUE," >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE);;" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT END;;" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT /" >>${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} PROMPT [GATHERING STATISTICS on the NEW TABLE] ..." >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} SET TIMING ON" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} BEGIN" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} DBMS_STATS.GATHER_TABLE_STATS (" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} ownname => upper('${OWNER}')," >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} TABNAME => upper('${OBJECT_NAME}')," >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} DEGREE => DBMS_STATS.AUTO_DEGREE," >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} CASCADE => TRUE," >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE);" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} END;" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} /" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} SET TIMING OFF" >>${REBUILDTABLESCRIPT} | |
echo "${HASHSTATS} PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT FINALLY: PLEASE DOUBLE CHECK THE PROCESS, IF YOU ARE SATISFIED, DROP THE OLD TABLE USING THIS COMMAND:" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT -------- --------------------------------------------------------------------------------------------" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT [DROP TABLE ${OWNER}.${OBJECT_NAME_INT} CASCADE CONSTRAINTS PURGE;]">>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT [SCRIPT COMPLETED.]" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT SCRIPT: [${REBUILDTABLESCRIPT}]" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT LOGFILE: [${REBUILDTABLESPOOL}]" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "EXIT" >>${REBUILDTABLESCRIPT} | |
echo "#!/bin/bash" > ${REBUILDTABLESCRIPTRUNNER} | |
echo "nohup ${ORACLE_HOME}/bin/sqlplus \"/ as sysdba\" @${REBUILDTABLESCRIPT} | tee ${REBUILDTABLESPOOL} 2>&1 &" >>${REBUILDTABLESCRIPTRUNNER} | |
chmod 740 ${REBUILDTABLESCRIPTRUNNER} | |
echo "" | |
echo -e "\033[33;5mFeel free to EXIT from this session as the REBUILD operation is running in the BACKGROUND.]\033[0m" | |
echo "" | |
source ${REBUILDTABLESCRIPTRUNNER} | |
exit 1 ;; | |
esac | |
break ;; | |
n|N|no|NO|No) echo "Moving to Other REBUILD Options..."; break ;; | |
*) echo "Please enter a VALID answer [Y|N]" ;; | |
esac | |
done | |
;; | |
*object*) echo "The INTERIM TABLE [${OWNER}.${OBJECT_NAME_INT}] is already exist!";echo "Please check and run the script again.";echo "Script Terminated!"; exit 1;; | |
*) echo "";echo -e "\033[33;5mDBMS_REDEIFINITION cannot be used: The INTERIM table [${OWNER}.${OBJECT_NAME_INT}] cannot be created! Moving to 'ALTER TABLE MOVE' option ...\033[0m";; | |
esac | |
else | |
echo "" | |
echo -e "\033[33;5mDBMS_REDEIFINITION is NOT AVAILABLE in this Database Edition!\033[0m" | |
fi | |
# ######################################## | |
# SQLPLUS: TABLE REBUILD: | |
# ######################################## | |
echo "" | |
echo "Exploring \"ALTER TABLE MOVE\" Option ..." | |
case ${ORACLE12_ONLINE} in | |
"ONLINE UPDATE INDEXES") echo -e "\033[33;5mVoila! The Database Version & Edition Support The Online Table Rebuild [Minimal Downtime On The Table!]\033[0m" | |
echo "" | |
echo "Entering ALTER TABLE MOVE ONLINE Mode ..." | |
echo "";; | |
*) echo "" | |
echo "ALTER TABLE MOVE ONLINE is NOT available in this DB Edition!" | |
echo "" | |
printf "`echo "Entering ALTER TABLE MOVE ["` `echo -e "\033[33;5mLegacy Mode\033[0m"` `echo "] ..."`\n" | |
echo "";; | |
esac | |
# Checking if the table has any of NON SUPPORTED data types for ALTER TABLE MOVE operation: | |
VALDATATYPENOSUPPORTRAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select count(*) from dba_tab_columns where owner=upper('${OWNER}') and table_name=upper('${OBJECT_NAME}') and DATA_TYPE in ('LONG','LONG RAW'); | |
exit; | |
EOF | |
) | |
VALDATATYPENOSUPPORT=`echo ${VALDATATYPENOSUPPORTRAW}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
if [ ${VALDATATYPENOSUPPORT} -eq 1 ] | |
then | |
echo -e "\033[33;5m[Table [${OWNER}.${OBJECT_NAME}] Contains UN-SUPPORTED \"LONG\" DATA TYPE for \"ALTER TABLE MOVE\" operation.]\033[0m" | |
echo "" | |
echo "Script Terminated!" | |
echo "" | |
exit 1 | |
fi | |
# Checking DEFAULT LOGGING option: | |
VALDEFAULTLOGGINGRAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select LOGGING from DBA_TABLES where owner=upper('${OWNER}') and table_name=upper('${OBJECT_NAME}'); | |
exit; | |
EOF | |
) | |
VALDEFAULTLOGGING=`echo ${VALDEFAULTLOGGINGRAW}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
case ${VALDEFAULTLOGGING} in | |
NO) echo "[INFO: LOGGING is NOT enabled on table [${OWNER}.${OBJECT_NAME}]. Preserving the NOLOGGING setting.]";export DISABLELOGGING="--";; | |
esac | |
# Checking ORIGINAL PARALLELIESM DEGREE: | |
VALTABPARALLELDEGREERAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select DEGREE from DBA_TABLES where owner=upper('${OWNER}') and table_name=upper('${OBJECT_NAME}'); | |
exit; | |
EOF | |
) | |
VALTABPARALLELDEGREE=`echo ${VALTABPARALLELDEGREERAW}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
if [ ${VALTABPARALLELDEGREE} -gt 1 ] | |
then | |
echo "[INFO: TABLE's DEFAULT PARALLELISM DEGREE is: ${VALTABPARALLELDEGREE}]"; export VALTABPARALLELDEGREE | |
sleep 1 | |
fi | |
# NEW TABLESPACE SELECTION: | |
# ######################## | |
echo | |
echo "Enter the NEW TABLESPACE name if you want to move this table to a different TABLESPACE: [Leave it BLANK if you want to leave it on same TABLESPACE]" | |
echo "======================================================================================" | |
while read NEW_TABLESPACE_ANSWER | |
do | |
case ${NEW_TABLESPACE_ANSWER} in | |
"") export TABLESPACE_NAME=''; break;; | |
*) | |
TBS_EXIST_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select count(*) from dba_tablespaces where tablespace_name=upper('${NEW_TABLESPACE_ANSWER}'); | |
exit; | |
EOF | |
) | |
TBS_EXIST=`echo ${TBS_EXIST_RAW} | awk '{print $NF}'` | |
case ${TBS_EXIST} in | |
0) echo; echo "The Provided tablespace is NOT EXIST!." | |
echo "" | |
echo "Please Enter a VALID TABLESPACE NAME:" | |
echo "------------------------------------";; | |
1) | |
echo "" | |
echo "Tablespace exist." | |
echo "" | |
echo "Checking if the new tablespace has sufficent space to host the table ..." | |
echo "" | |
TBS_FREE_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select /*+RULE*/ round(((tablespace_size*${blksize})/(1024*1024)) - ((used_space*${blksize})/(1024*1024))) | |
from dba_tablespace_usage_metrics where tablespace_name=upper('${NEW_TABLESPACE_ANSWER}'); | |
prompt | |
exit; | |
EOF | |
) | |
TBS_FREE=`echo ${TBS_FREE_RAW} | awk '{print $NF}'` | |
if [ ${TBS_FREE} -lt ${TABLESIZEPLUSMARGIN} ] | |
then | |
REQUIREDSPACE=$(awk "BEGIN {print ${TABLESIZE} - ${TBS_FREE}}") | |
echo "" | |
echo -e "\033[33;5mThe underlying tablespace [${NEW_TABLESPACE_ANSWER}] has NO SUFFICIENT FREE SPACE to cater to this operation!\033[0m" | |
echo "TABLE + INDEXES SIZE= ${TABLESIZE} MB" | |
echo "TABLESPACE FREE SPACE= ${TBS_FREE} MB" | |
echo "You need to add at least ${REQUIREDSPACE} MB of extra space to [${NEW_TABLESPACE_ANSWER}] tablespace and then re-run the rebuild script again." | |
echo "" | |
echo "Please Enter a TABLESPACE NAME that has sufficent space:" | |
echo "-------------------------------------------------------"; | |
else | |
echo "Tablespace [${NEW_TABLESPACE_ANSWER}] has sufficent free space." | |
export TABLESPACE_NAME="TABLESPACE ${NEW_TABLESPACE_ANSWER}" | |
break; | |
fi | |
esac | |
esac | |
done | |
# Checking if COMPRESSION option is enabled: | |
COMPRESSION_OPTION_RAW=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" << EOF | |
set pages 0 feedback off echo off; | |
SELECT count(*) from v\$option where parameter='Basic Compression' and value='TRUE'; | |
exit; | |
EOF | |
) | |
COMPRESSION_OPTION=`echo ${COMPRESSION_OPTION_RAW} | awk '{print $NF}'` | |
if [ ${COMPRESSION_OPTION} -eq 1 ] | |
then | |
echo | |
echo "Do you want to use BASIC COMPRESSION option while rebuilding the table?: [Y|N] N [Compression Will Save much of space]" | |
echo "========================================================================" | |
while read COMPRESS_ANSWER | |
do | |
case ${COMPRESS_ANSWER} in | |
y|Y|yes|YES|Yes)export COMPRESS="COMPRESS"; break;; | |
""|n|N|no|NO|No)export COMPRESS=""; break;; | |
*) echo "Please enter a VALID answer [Y|N]" ;; | |
esac | |
done | |
else | |
echo "" | |
echo -e "\033[33;5mBASIC COMPRESSION option is NOT available in this Database Edition!\033[0m" | |
echo "" | |
fi | |
# ############################################# | |
# SETTING PCT_FREE FOR TABLE AFTER THE REBUILD: | |
# ############################################# | |
VALDEFAULTPCTFREE=$(${ORACLE_HOME}/bin/sqlplus -S "/ as sysdba" <<EOF | |
set pages 0 feedback off lines 1000; | |
prompt | |
select PCT_FREE from DBA_TABLES where owner=upper('${OWNER}') and table_name=upper('${OBJECT_NAME}'); | |
exit; | |
EOF | |
) | |
DEFAULTPCTFREE=`echo ${VALDEFAULTPCTFREE}|perl -lpe'$_ = reverse' |awk '{print $1}'|perl -lpe'$_ = reverse'|cut -f1 -d '.'` | |
echo "" | |
echo "INFO: Current PCTFREE: ${DEFAULTPCTFREE}" | |
echo "INFO: Number of \"UPDATE\" transactions on the table since the last Statistics Gather on [${LASTANALYZED}]: ${TABUPDATES}" | |
echo | |
echo | |
echo "Specify the PCTFREE for the New Table: [How much %Free space will be left in each block for future updates | Current ${DEFAULTPCTFREE}%]" | |
echo "=====================================" | |
echo "Note: The SMALLER the PCTFREE the SMALLER the table size after the rebuild. [Recommended for Archival/Datawarehouse Tables]" | |
echo "Note: If the table is highly updated it's recommended to keep the current PCTFREE: ${DEFAULTPCTFREE}" | |
echo "Leave it BLANK and hit Enter to keep the default PCTFREE." | |
while read TABPCTFREEVAL | |
do | |
case ${TABPCTFREEVAL} in | |
"") export TABPCTFREE=${DEFAULTPCTFREE} | |
break;; | |
*[!0-9]*) echo "Please enter a valid NUMBER:";; | |
*) export TABPCTFREE=${TABPCTFREEVAL} | |
break;; | |
esac | |
done | |
echo | |
echo "Specify the PCTFREE for the Table's Indexes: [How much %Free space will be left in each block for future updates]" | |
echo "===========================================" | |
echo "Note: The SMALLER the PCTFREE the SMALLER the index size after the rebuild." | |
echo "Note: If the table is highly updated it's recommended to keep the current PCTFREE: ${DEFAULTPCTFREE}" | |
echo "Leave it BLANK and hit Enter to accept the default PCTFREE=10" | |
while read IDXPCTFREEVAL | |
do | |
case ${IDXPCTFREEVAL} in | |
"") export IDXPCTFREE=10 | |
break;; | |
*[!0-9]*) echo "Please enter a valid NUMBER:";; | |
*) export IDXPCTFREE=${IDXPCTFREEVAL} | |
break;; | |
esac | |
done | |
# INFO AND REBUILD PROCEDURE: | |
# ########################## | |
REBUILDTABLESCRIPT=${USR_ORA_HOME}/REBUILDTABLESCRIPT-${OWNER}.${OBJECT_NAME}.sql | |
REBUILDINDEXSCRIPT=${USR_ORA_HOME}/REBUILDINDEXSCRIPT-${OWNER}.${OBJECT_NAME}.sql | |
REBUILDTABLESCRIPTRUNNER=${USR_ORA_HOME}/REBUILDTABLESCRIPT-${OWNER}.${OBJECT_NAME}.sh | |
REBUILDTABLESPOOL=${USR_ORA_HOME}/REBUILDTABLESCRIPT-${OWNER}.${OBJECT_NAME}.log | |
REBUILDINDEXSPOOL=${USR_ORA_HOME}/REBUILDINDEXSCRIPT-${OWNER}.${OBJECT_NAME}.log | |
echo "spool ${REBUILDTABLESPOOL}" > ${REBUILDTABLESCRIPT} | |
echo "PROMPT THIS OPERATION IS LOGGED IN: [${REBUILDTABLESPOOL}]" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} PROMPT ********************************************************************************">> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} PROMPT It's HIGHLY RECOMMENDED to run this script within a DOWNTIME WINDOW, ">> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} PROMPT To AVOID INTERRUPTING long running queries against the table during the rebuild.">> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} PROMPT ********************************************************************************">> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} exec dbms_lock.sleep(9);" >> ${REBUILDTABLESCRIPT} | |
echo "set pages 0 feedback off lines 168" >> ${REBUILDTABLESCRIPT} | |
echo "EXEC DBMS_SESSION.set_identifier('REBUILDING_${OWNER}.${OBJECT_NAME}');" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ***************" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT Session Details:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ***************" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "select 'OSPID: '||p.spid from v\$session s, v\$process p where s.sid=(select sid from v\$mystat where rownum=1) and s.paddr=p.addr;" >> ${REBUILDTABLESCRIPT} | |
echo "select 'SID: '||sid from v\$mystat where rownum = 1;" >> ${REBUILDTABLESCRIPT} | |
echo "select 'Serial#: '||s.serial# from v\$session s where s.sid = (select sid from v\$mystat where rownum = 1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT You can KILL this session using this command:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ********************************************" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "select 'ALTER SYSTEM DISCONNECT SESSION '''||sid||','||serial#||''' IMMEDIATE;' from v\$session where sid = (select sid from v\$mystat where rownum = 1);" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "set feedback on" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT TABLE INFO BEFORE THE REBUILD:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT *****************************" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "set linesize 168 pages 1000 heading on" >> ${REBUILDTABLESCRIPT} | |
echo "col \"OWNER.TABLE\" for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col tablespace_name for a20" >> ${REBUILDTABLESCRIPT} | |
echo "col \"READONLY\" for a8" >> ${REBUILDTABLESCRIPT} | |
echo "col \"%RECLAIM\" for 999" >> ${REBUILDTABLESCRIPT} | |
echo "col LAST_ANALYZED for a13" >> ${REBUILDTABLESCRIPT} | |
echo "col COMPRESSION for a8" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "select /*+RULE*/ t.owner||'.'||t.table_name \"OWNER.TABLE\",t.TABLESPACE_NAME,d.extents,t.logging," >> ${REBUILDTABLESCRIPT} | |
echo "t.COMPRESSION,t.READ_ONLY \"READONLY\",o.created,to_char(t.LAST_ANALYZED, 'DD-MON-YYYY') LAST_ANALYZED" >> ${REBUILDTABLESCRIPT} | |
echo ",round(d.bytes/1025/1024) SIZE_MB," >> ${REBUILDTABLESCRIPT} | |
echo "round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * t.avg_row_len/1024/1024), 2) \"FRAGMENTED_SPACE_MB\"," >> ${REBUILDTABLESCRIPT} | |
echo "((round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * t.avg_row_len/1024/1024), 2)) /" >> ${REBUILDTABLESCRIPT} | |
echo "round((t.blocks * ${blksize}/1024/1024), 2)) * 100 \"%RECLAIM\"" >> ${REBUILDTABLESCRIPT} | |
echo "from dba_tables t, dba_objects o, dba_segments d" >> ${REBUILDTABLESCRIPT} | |
echo "where t.owner= upper('${OWNER}')" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name = upper('${OBJECT_NAME}')" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=t.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and o.object_name=t.table_name" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=d.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name=d.SEGMENT_NAME;" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT LOBS:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT -----" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "col SEGMENT_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col INDEX_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col COMPRESSION for a8" >> ${REBUILDTABLESCRIPT} | |
echo "col SECUREFILE for a10" >> ${REBUILDTABLESCRIPT} | |
echo "col COLUMN_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "select SEGMENT_NAME,COLUMN_NAME,TABLESPACE_NAME,INDEX_NAME,SECUREFILE,COMPRESSION from dba_lobs" >> ${REBUILDTABLESCRIPT} | |
echo "where owner=upper('${OWNER}') and table_name = upper('${OBJECT_NAME}');" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "set feedback on" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT INDEXES BEFORE THE REBUILD:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ---------------------------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN OWNER FORMAT A25 heading \"Index Owner\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN INDEX_NAME FORMAT A30 heading \"Index Name\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN COLUMN_NAME FORMAT A25 heading \"On Column\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN COLUMN_POSITION FORMAT 9999 heading \"Pos\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN \"INDEX\" FORMAT A35" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN INDEX_TYPE FOR A16" >> ${REBUILDTABLESCRIPT} | |
echo "SELECT /*+RULE*/ IND.OWNER||'.'||IND.INDEX_NAME \"INDEX\"," >> ${REBUILDTABLESCRIPT} | |
echo " IND.INDEX_TYPE," >> ${REBUILDTABLESCRIPT} | |
echo " COL.COLUMN_NAME," >> ${REBUILDTABLESCRIPT} | |
echo " COL.COLUMN_POSITION," >> ${REBUILDTABLESCRIPT} | |
echo " IND.TABLESPACE_NAME," >> ${REBUILDTABLESCRIPT} | |
echo " IND.STATUS," >> ${REBUILDTABLESCRIPT} | |
echo " IND.UNIQUENESS," >> ${REBUILDTABLESCRIPT} | |
echo " IND.LOGGING," >> ${REBUILDTABLESCRIPT} | |
echo " IND.LAST_ANALYZED,round(d.bytes/1024/1024) SIZE_MB" >> ${REBUILDTABLESCRIPT} | |
echo "FROM SYS.DBA_INDEXES IND," >> ${REBUILDTABLESCRIPT} | |
echo " SYS.DBA_IND_COLUMNS COL," >> ${REBUILDTABLESCRIPT} | |
echo " DBA_SEGMENTS d" >> ${REBUILDTABLESCRIPT} | |
echo "WHERE IND.TABLE_NAME = upper('${OBJECT_NAME}')" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.TABLE_OWNER = upper('${OWNER}')" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.TABLE_NAME = COL.TABLE_NAME" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.OWNER = d.OWNER(+)" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.OWNER = COL.INDEX_OWNER" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.TABLE_OWNER = COL.TABLE_OWNER" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.INDEX_NAME = COL.INDEX_NAME" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.INDEX_NAME = d.SEGMENT_NAME(+);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT CONSTRAINTS BEFORE THE REBUILD:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT -------------------------------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "col CONSTRAINT_NAME for a30" >> ${REBUILDTABLESCRIPT} | |
echo "col R_CONSTRAINT_NAME for a30" >> ${REBUILDTABLESCRIPT} | |
echo "select CONSTRAINT_NAME,CONSTRAINT_TYPE,R_CONSTRAINT_NAME,STATUS,DEFERRED,INDEX_NAME from dba_constraints where">> ${REBUILDTABLESCRIPT} | |
echo "OWNER=upper('${OWNER}') and TABLE_NAME=upper('${OBJECT_NAME}') order by CONSTRAINT_TYPE;" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [Setting the PARALLELISM FACTOR to ${PARALLEL_DEGREE}] ..." >> ${REBUILDTABLESCRIPT} | |
echo "alter session enable parallel dml;" >> ${REBUILDTABLESCRIPT} | |
echo "alter session enable parallel ddl;" >> ${REBUILDTABLESCRIPT} | |
echo "alter session enable parallel query;" >> ${REBUILDTABLESCRIPT} | |
echo "alter session force parallel dml parallel ${PARALLEL_DEGREE};" >> ${REBUILDTABLESCRIPT} | |
echo "alter session force parallel ddl parallel ${PARALLEL_DEGREE};" >> ${REBUILDTABLESCRIPT} | |
echo "alter session force parallel query parallel ${PARALLEL_DEGREE};" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [Setting the SESSION DDL WAIT FOR LOCK to 5 minutes] ..." >> ${REBUILDTABLESCRIPT} | |
echo "alter session set ddl_lock_timeout=300;" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [Setting the SESSION RESUMABLE TIMEOUT to 6 Hours] ..." >> ${REBUILDTABLESCRIPT} | |
echo "ALTER SESSION ENABLE RESUMABLE TIMEOUT 21600 NAME 'REBUILD_OF_TABLE_${OBJECT_NAME}';" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [Start REBUILDING the table using: ALTER TABLE MOVE ${ORACLE12_ONLINE} command] ..." >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT TABLE REBUILD PROCEDURE WILL START WITHIN 5 Seconds ..." >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ---------------------------------------------------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "SET FEEDBACK OFF" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(4);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [5]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [4]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [3]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [2]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [1]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_lock.sleep(1);" >> ${REBUILDTABLESCRIPT} | |
echo "--Exit the script if any failure encountered at any stage:" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "set serveroutput on" >> ${REBUILDTABLESCRIPT} | |
echo "WHENEVER SQLERROR EXIT SQL.SQLCODE;" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [START REBUILDING TABLE [${OWNER}.${OBJECT_NAME}]] ..." >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [SETTING TABLE [${OWNER}.${OBJECT_NAME}] IN NOLOGGING MODE] ..." >> ${REBUILDTABLESCRIPT} | |
echo "ALTER TABLE ${OWNER}.${OBJECT_NAME} NOLOGGING;" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [REBUILDING TABLE [${OWNER}.${OBJECT_NAME}] [This may take quite long depending on the table size] ..." >> ${REBUILDTABLESCRIPT} | |
echo "SET FEEDBACK ON" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT Keep checking the progress using this statement:" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT -----------------------------------------------" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col OPERATION for a21" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col \"%DONE\" for 999.999" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col \"STARTED|MIN_ELAPSED|REMAIN\" for a26" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col MESSAGE for a90" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT col \"USERNAME| SID,SERIAL#\" for a28" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT select USERNAME||'| '||SID||','||SERIAL# \"USERNAME| SID,SERIAL#\",SQL_ID,round(SOFAR/TOTALWORK*100,2) \"%DONE\"" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT ,to_char(START_TIME,'DD-Mon HH24:MI')||'| '||trunc(ELAPSED_SECONDS/60)||'|'||trunc(TIME_REMAINING/60) \"STARTED|MIN_ELAPSED|REMAIN\" ,MESSAGE" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT from v\$session_longops" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT where TARGET LIKE UPPER('%${OBJECT_NAME}%') and TOTALWORK <> '0' and SOFAR/TOTALWORK*100 <>'100'" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT order by \"STARTED|MIN_ELAPSED|REMAIN\" desc, \"USERNAME| SID,SERIAL#\";;" >>${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT EXECUTING: [ALTER TABLE ${OWNER}.${OBJECT_NAME} MOVE ${ORACLE12_ONLINE} ${TABLESPACE_NAME} PARALLEL ${PARALLEL_DEGREE} PCTFREE ${TABPCTFREE} ${COMPRESS};]">> ${REBUILDTABLESCRIPT} | |
echo "ALTER TABLE ${OWNER}.${OBJECT_NAME} MOVE ${ORACLE12_ONLINE} ${TABLESPACE_NAME} PARALLEL ${PARALLEL_DEGREE} PCTFREE ${TABPCTFREE} ${COMPRESS};">> ${REBUILDTABLESCRIPT} | |
echo "PROMPT COMPLETED: [ALTER TABLE ${OWNER}.${OBJECT_NAME} MOVE ${ORACLE12_ONLINE} ${TABLESPACE_NAME} PARALLEL ${PARALLEL_DEGREE} PCTFREE ${TABPCTFREE} ${COMPRESS};]" >>${REBUILDTABLESCRIPT} | |
echo "PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${DISABLELOGGING} PROMPT [SETTING TABLE [${OWNER}.${OBJECT_NAME}] IN LOGGING MODE] ..." >> ${REBUILDTABLESCRIPT} | |
echo "${DISABLELOGGING} ALTER TABLE ${OWNER}.${OBJECT_NAME} LOGGING ;" >> ${REBUILDTABLESCRIPT} | |
echo "${DISABLELOGGING} PROMPT" >>${REBUILDTABLESCRIPT} | |
echo "${DISABLEPARALLELISM} PROMPT [SETTING TABLE [${OWNER}.${OBJECT_NAME}] TO ITS ORIGINAL PARALLELISM DEGREE ${VALTABPARALLELDEGREE}] ...">> ${REBUILDTABLESCRIPT} | |
echo "${DISABLEPARALLELISM} ALTER TABLE ${OWNER}.${OBJECT_NAME} PARALLEL ${VALTABPARALLELDEGREE};" >> ${REBUILDTABLESCRIPT} | |
echo "" >>${REBUILDTABLESCRIPT} | |
echo "SET TERMOUT OFF PAGES 1000 LINESIZE 167 HEADING OFF FEEDBACK OFF VERIFY OFF ECHO OFF" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} SPOOL ${REBUILDINDEXSCRIPT}" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} select 'SPOOL ${REBUILDINDEXSPOOL}' from dual;" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} select 'ALTER INDEX '||owner||'.\"'||index_name||'\" REBUILD ${ONLINE_REBUILD} ${TABLESPACE_NAME} PARALLEL ${PARALLEL_DEGREE} PCTFREE ${IDXPCTFREE} ${COMPRESS};'">> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} from dba_indexes where TABLE_OWNER=upper('${OWNER}') and TABLE_NAME=upper('${OBJECT_NAME}');" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} select 'ALTER INDEX '||owner||'.\"'||index_name||'\" PARALLEL ${VALTABPARALLELDEGREE};'from dba_indexes where TABLE_OWNER=upper('${OWNER}') and TABLE_NAME=upper('${OBJECT_NAME}');" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} select 'spool off' from dual;" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} SPOOL OFF" >>${REBUILDTABLESCRIPT} | |
echo "SET TERMOUT ON ECHO OFF FEEDBACK ON VERIFY OFF" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} PROMPT [REBUILDING INDEXES] ..." >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} @${REBUILDINDEXSCRIPT}" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} PROMPT [INDEXES REBUILD COMPLETED.]" >> ${REBUILDTABLESCRIPT} | |
echo "${ORACLE12_HASH} PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [GATHERING STATISTICS ON TABLE [${OWNER}.${OBJECT_NAME}] AND ITS INDEXES] ..." >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT " >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [UNLOCKING TABLE STATISTICS ...]" >> ${REBUILDTABLESCRIPT} | |
echo "exec dbms_stats.unlock_table_stats('${OWNER}', '${OBJECT_NAME}');" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT " >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [GATHERING TABLE STATISTICS ...]" >> ${REBUILDTABLESCRIPT} | |
echo "BEGIN" >> ${REBUILDTABLESCRIPT} | |
echo "DBMS_STATS.GATHER_TABLE_STATS (" >> ${REBUILDTABLESCRIPT} | |
echo "ownname => upper('${OWNER}')," >> ${REBUILDTABLESCRIPT} | |
echo "tabname => upper('${OBJECT_NAME}')," >> ${REBUILDTABLESCRIPT} | |
echo "cascade => TRUE," >> ${REBUILDTABLESCRIPT} | |
echo "METHOD_OPT => 'FOR ALL COLUMNS SIZE SKEWONLY'," >> ${REBUILDTABLESCRIPT} | |
echo "DEGREE => DBMS_STATS.AUTO_DEGREE," >> ${REBUILDTABLESCRIPT} | |
echo "estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE);" >> ${REBUILDTABLESCRIPT} | |
echo "END;" >> ${REBUILDTABLESCRIPT} | |
echo "/" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [GATHER STATISTICS COMPLETED.]" >> ${REBUILDTABLESCRIPT} | |
echo "${HASHNOTIFY} exec dbms_system.ksdwrt(3,'ORA-NOTIFICATION: REBUILD OF TABLE [${OWNER}.${OBJECT_NAME}] COMPLETED. LOGFILE: ${REBUILDTABLESPOOL}');">>${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "set feedback on" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT TABLE INFO AFTER THE REBUILD:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ****************************" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "set linesize 168 pages 1000 heading on" >> ${REBUILDTABLESCRIPT} | |
echo "col \"OWNER.TABLE\" for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col tablespace_name for a20" >> ${REBUILDTABLESCRIPT} | |
echo "col \"READONLY\" for a8" >> ${REBUILDTABLESCRIPT} | |
echo "col \"%RECLAIM\" for 999" >> ${REBUILDTABLESCRIPT} | |
echo "col LAST_ANALYZED for a13" >> ${REBUILDTABLESCRIPT} | |
echo "col PCT_FREE for 99999999" >> ${REBUILDTABLESCRIPT} | |
echo "col COMPRESSION for a8" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "select /*+RULE*/ t.owner||'.'||t.table_name \"OWNER.TABLE\",t.TABLESPACE_NAME,d.extents,t.PCT_FREE,t.logging" >> ${REBUILDTABLESCRIPT} | |
echo ",t.COMPRESSION,t.READ_ONLY \"READONLY\",to_char(t.LAST_ANALYZED, 'DD-MON-YYYY') LAST_ANALYZED" >> ${REBUILDTABLESCRIPT} | |
echo ",round(d.bytes/1025/1024) SIZE_MB," >> ${REBUILDTABLESCRIPT} | |
echo "round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * t.avg_row_len/1024/1024), 2) \"FRAGMENTED_SPACE_MB\"," >> ${REBUILDTABLESCRIPT} | |
echo "((round((t.blocks * ${blksize}/1024/1024), 2) - round((t.num_rows * t.avg_row_len/1024/1024), 2)) / round((t.blocks * ${blksize}/1024/1024), 2)) * 100 \"%RECLAIM\"" >> ${REBUILDTABLESCRIPT} | |
echo "from dba_tables t, dba_objects o, dba_segments d" >> ${REBUILDTABLESCRIPT} | |
echo "where t.owner= upper('${OWNER}')" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name = upper('${OBJECT_NAME}')" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=t.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and o.object_name=t.table_name" >> ${REBUILDTABLESCRIPT} | |
echo "and o.owner=d.owner" >> ${REBUILDTABLESCRIPT} | |
echo "and t.table_name=d.SEGMENT_NAME;" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT LOBS:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT -----" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "col SEGMENT_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col INDEX_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "col COMPRESSION for a8" >> ${REBUILDTABLESCRIPT} | |
echo "col SECUREFILE for a10" >> ${REBUILDTABLESCRIPT} | |
echo "col COLUMN_NAME for a35" >> ${REBUILDTABLESCRIPT} | |
echo "select SEGMENT_NAME,COLUMN_NAME,TABLESPACE_NAME,INDEX_NAME,SECUREFILE,COMPRESSION from dba_lobs" >> ${REBUILDTABLESCRIPT} | |
echo "where owner=upper('${OWNER}') and table_name = upper('${OBJECT_NAME}');" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT INDEXES AFTER THE REBUILD:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT --------------------------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "set feedback on" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN OWNER FORMAT A25 heading \"Index Owner\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN INDEX_NAME FORMAT A30 heading \"Index Name\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN COLUMN_NAME FORMAT A25 heading \"On Column\"" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN COLUMN_POSITION FORMAT 999 heading Pos" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN INDEX FORMAT A35" >> ${REBUILDTABLESCRIPT} | |
echo "COLUMN INDEX_TYPE FORMAT A13" >> ${REBUILDTABLESCRIPT} | |
echo "SELECT /*+RULE*/ IND.OWNER||'.'||IND.INDEX_NAME \"INDEX\"," >> ${REBUILDTABLESCRIPT} | |
echo " IND.INDEX_TYPE," >> ${REBUILDTABLESCRIPT} | |
echo " IND.PCT_FREE," >> ${REBUILDTABLESCRIPT} | |
echo " COL.COLUMN_NAME," >> ${REBUILDTABLESCRIPT} | |
echo " COL.COLUMN_POSITION," >> ${REBUILDTABLESCRIPT} | |
echo " IND.TABLESPACE_NAME," >> ${REBUILDTABLESCRIPT} | |
echo " IND.STATUS," >> ${REBUILDTABLESCRIPT} | |
echo " IND.UNIQUENESS," >> ${REBUILDTABLESCRIPT} | |
echo " IND.LOGGING," >> ${REBUILDTABLESCRIPT} | |
echo " IND.LAST_ANALYZED,round(d.bytes/1024/1024) SIZE_MB" >> ${REBUILDTABLESCRIPT} | |
echo "FROM SYS.DBA_INDEXES IND," >> ${REBUILDTABLESCRIPT} | |
echo " SYS.DBA_IND_COLUMNS COL," >> ${REBUILDTABLESCRIPT} | |
echo " DBA_SEGMENTS d" >> ${REBUILDTABLESCRIPT} | |
echo "WHERE IND.TABLE_NAME = upper('${OBJECT_NAME}')" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.TABLE_OWNER = upper('${OWNER}')" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.TABLE_NAME = COL.TABLE_NAME" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.OWNER = d.OWNER(+)" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.OWNER = COL.INDEX_OWNER" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.TABLE_OWNER = COL.TABLE_OWNER" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.INDEX_NAME = COL.INDEX_NAME" >> ${REBUILDTABLESCRIPT} | |
echo "AND IND.INDEX_NAME = d.SEGMENT_NAME(+);" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT CONSTRAINTS AFTER THE REBUILD:" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT ------------------------------" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "col CONSTRAINT_NAME for a30" >> ${REBUILDTABLESCRIPT} | |
echo "col R_CONSTRAINT_NAME for a30" >> ${REBUILDTABLESCRIPT} | |
echo "select CONSTRAINT_NAME,CONSTRAINT_TYPE,R_CONSTRAINT_NAME,STATUS,DEFERRED,INDEX_NAME from dba_constraints where">> ${REBUILDTABLESCRIPT} | |
echo "OWNER=upper('${OWNER}') and TABLE_NAME=upper('${OBJECT_NAME}') order by CONSTRAINT_TYPE;" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [TABLE REBUILD OPERATION COMPLETED.]" >> ${REBUILDTABLESCRIPT} | |
echo "" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT [SCRIPT COMPLETED.]" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT SCRIPT: [${REBUILDTABLESCRIPT}]" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT LOGFILE: [${REBUILDTABLESPOOL}]" >> ${REBUILDTABLESCRIPT} | |
echo "PROMPT" >> ${REBUILDTABLESCRIPT} | |
echo "EXIT" >> ${REBUILDTABLESCRIPT} | |
echo "#!/bin/bash" > ${REBUILDTABLESCRIPTRUNNER} | |
echo "nohup ${ORACLE_HOME}/bin/sqlplus \"/ as sysdba\" @${REBUILDTABLESCRIPT} | tee ${REBUILDTABLESPOOL} 2>&1 &" >>${REBUILDTABLESCRIPTRUNNER} | |
chmod 740 ${REBUILDTABLESCRIPTRUNNER} | |
echo "" | |
echo -e "\033[33;5mFeel free to EXIT from this session as the REBUILD operation is running in the BACKGROUND.\033[0m" | |
echo "" | |
source ${REBUILDTABLESCRIPTRUNNER} | |
# ############# | |
# END OF SCRIPT | |
# ############# | |
# REPORT BUGS to: [email protected] | |
# DISCLAIMER: THIS SCRIPT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY. IT IS PROVIDED "AS IS". | |
# DOWNLOAD THE LATEST VERSION OF DATABASE ADMINISTRATION BUNDLE FROM: http://dba-tips.blogspot.com/2014/02/oracle-database-administration-scripts.html |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment