解决PG索引膨胀(reindex)

#!/bin/bash
#当表的数据小于20万则对表做 reindex table xxx操作
#否则先删除索引(唯一约束索引,及主键除则 reindx index xxx),然后再创建该索引
#zhaowenzhong 2019-04-02

date=`date +"%Y%m%d%H%M"`
v_constant=200000
v_hour=0
v_param=$#

if [ $v_param -ge 3 ];then
        echo "Invalid argument!! E.g sh pg-reindex-all.sh vlnx191001.xxx.cn OR sh pg-reindex-all.sh vlnx191001.xxx.cn  \" db1,db2,db3,...\""
        exit 1
fi


pghosts=$1

if [ -n "$pghosts" ];then

        hostname=${pghosts%%.*}
        filename=$hostname'-reindex-'$date

        for pghostname in $pghosts
        do
                if [ $v_param -eq 1 ];then
                        dblist=$(psql  -h $pghostname -U zhaowz -d postgres -c "select datname from pg_database where datname not in ('postgres','template0','template1','repmgr')" -A -t)
                elif [ $v_param -eq 2 ];then
                        dblist=$(psql  -h $pghostname -U zhaowz -d postgres -c "select datname from pg_database where datname=any('{$2}')" -A -t)
                fi

                if [ -z "$dblist" ];then
                        echo "Invalid dbname OR Invalid hostname !!!" >> /home/zhaowz/logs/$filename.log
                        exit 1
                fi


                for db in $dblist
                do
                        v_hour=$(date "+%k")
                        if [[ ${v_hour} -ge 1 && ${v_hour} -lt 7 ]]; then

                                echo "$db : `date +"%Y%m%d%H%M%S"` Begin ">>/home/zhaowz/logs/$filename.log
                                tables=$(psql  -h $pghostname -U zhaowz -d $db -c "select tablename from pg_tables where schemaname='public'" -A -t)

                        for table in $tables
                        do

                                v_count=0
                                v_count=$(psql  -h $pghostname -U zhaowz -d $db -c "select reltuples from v_get_eachtable_size where relname='$table'" -A -t)

                                v_hour=$(date "+%k")

                                if [[ ${v_hour} -ge 1 && ${v_hour} -lt 7 ]]; then

                                        if [ $v_count -gt $v_constant ]; then
                                               #过滤出非 主键索引和唯一索引
                                                indexes=$(psql -h $pghostname -U zhaowz -d $db -c "select indexname from v_get_indexes_stats where relname='$table' and ((\"Unique\" !='Y' and \"Primary\" !='Y') or (\"Unique\" !='Y' and \"Primary\" ='N'))" -A -t)

                                                for idx_line in $indexes
                                                do

                                                        v_create_index=''
                                                        v_create_index=$(psql -h $pghostname -U zhaowz -d $db -c "select 'create index  if not exists '|| indexname || ' on '|| relname || ' USING '|| pg_get_indexdef || ';' from v_get_indexes_stats where relname='$table' and indexname='$idx_line'" -A -t)

                                                        #由于程序使用的是长连接模式,长连接模式会产生很多  idle in trans 状态,该状态会导致 reindex index 阻塞。故在reindex时 将该状态的连接 pg_terminate_backend 
                                                        v_idel_in_tran=''
                                                        v_idel_in_tran=$(psql -h $pghostname -U zhaowz -d $db -c "select 'pg_terminate_backend('||pid||');' from pg_stat_activity where state='idle in transaction'" -A -t)

                                                        if [ -n "$v_idel_in_tran" ]; then
                                                                for v_tran in $v_idel_in_tran
                                                                do
                                                                        psql -h $pghostname -U zhaowz -d postgres -c "select $v_tran"
                                                                done
                                                        fi

                                                        echo "$db.$table.$idx_line :`date +"%Y%m%d%H%M%S"` Begin drop  ">>/home/zhaowz/logs/$filename.log
                                                        psql -h $pghostname -U zhaowz -d $db -c "drop index $idx_line ;"
                                                        echo "$db.$table.$idx_line :`date +"%Y%m%d%H%M%S"` has finished drop ">>/home/zhaowz/logs/$filename.log


                                                        echo "$db.$table.$idx_line :`date +"%Y%m%d%H%M%S"` Begin create  ">>/home/zhaowz/logs/$filename.log
                                                        psql -h $pghostname -U zhaowz -d $db -c " $v_create_index">>/home/zhaowz/logs/$filename.log
                                                        echo "$db.$table.$idx_line :`date +"%Y%m%d%H%M%S"` has finished create ">>/home/zhaowz/logs/$filename.log
                                                        echo $v_create_index >> /home/zhaowz/logs/$filename.log

                                                done
                                                #过滤出 主键索引和唯一索引    
                                                indexes_pkey_uq=$(psql -h $pghostname -U zhaowz -d $db -c "select indexname from v_get_indexes_stats where relname='$table' and ((\"Unique\" ='Y' and \"Primary\" ='Y') or (\"Unique\" ='Y' and \"Primary\" ='N'))" -A -t)

                                                for idx_pkey_uq in $indexes_pkey_uq
                                                do

                                                        #由于程序使用的是长连接模式,长连接模式会产生很多  idle in trans 状态,该状态会导致 reindex index 阻塞。故在reindex时 将该状态的连接 pg_terminate_backend 
                                                        v_idel_in_tran=''
                                                        v_idel_in_tran=$(psql -h $pghostname -U zhaowz -d $db -c "select 'pg_terminate_backend('||pid||');' from pg_stat_activity where state='idle in transaction'" -A -t)

                                                        if [ -n "$v_idel_in_tran" ]; then
                                                                for v_tran in $v_idel_in_tran
                                                                do
                                                                        psql -h $pghostname -U zhaowz -d postgres -c "select $v_tran"
                                                                done
                                                        fi

                                                        echo "$db.$table.$indexes_pkey_uq :`date +"%Y%m%d%H%M%S"` Begin reindex  " >> /home/zhaowz/logs/$filename.log
                                                        psql -h $pghostname -U zhaowz -d $db -c "reindex index $indexes_pkey_uq ;"
                                                        echo "$db.$table.$indexes_pkey_uq :`date +"%Y%m%d%H%M%S"` has finished reindex " >> /home/zhaowz/logs/$filename.log
                                                done


                                        elif [[ $v_count -gt 0 && $v_count -lt $v_constant ]]; then
                                                v_hour=$(date "+%k")
                                                if [[ ${v_hour} -ge 1 && ${v_hour} -lt 7 ]]; then

                                                        #由于程序使用的是长连接模式,长连接模式会产生很多  idle in trans 状态,该状态会导致 reindex index 阻塞。故在reindex时 将该状态的连接 pg_terminate_backend 
                                                        v_idel_in_tran=''
                                                        v_idel_in_tran=$(psql -h $pghostname -U zhaowz -d $db -c "select 'pg_terminate_backend('||pid||');' from pg_stat_activity where state='idle in transaction'" -A -t)

                                                        if [ -n "$v_idel_in_tran" ]; then
                                                                for v_tran in $v_idel_in_tran
                                                                do
                                                                        psql -h $pghostname -U zhaowz -d postgres -c "select $v_tran"
                                                                done
                                                        fi

                                                        echo "$db.$table :`date +"%Y%m%d%H%M%S"` Begin reindex ">>/home/zhaowz/logs/$filename.log
                                                        psql  -h $pghostname -U zhaowz -d $db -c "reindex table $table"
                                                        echo "$db.$table :`date +"%Y%m%d%H%M%S"` has finished reindex ">>/home/zhaowz/logs/$filename.log
                                                fi
                                        fi

                                echo "$db.$table :`date +"%Y%m%d%H%M%S"` has Begin vacuum analyze  ">>/home/zhaowz/logs/$filename.log
                                psql  -h $pghostname -U zhaowz -d $db -c "vacuum analyze $table"
                                echo "$db.$table :`date +"%Y%m%d%H%M%S"` has finished vacuum analyze  ">>/home/zhaowz/logs/$filename.log

                                fi
                        done

                        fi
                done
        done
fi


 

你可能感兴趣的:(Postgresql)