# 提取报表的开始与结束的snap #!/bin/bash PSQL="psql" pushd `dirname $0` #获取间隔天数 if [ $interval_day"x" == "x" ] then interval_day=`$PSQL --user postgres --dbname mydb --quiet -t --command " select current_date-max(ts)::date +1 from pgstatspack_snap; "` fi echo "interval_day:"$interval_day commit=`$PSQL --user postgres --dbname mydb --quiet -t --command " select min(snapid),max(snapid) from pgstatspack_snap where ts>now()- interval '${interval_day} day'; "` #获取最小与最大的快照id STARTSNAP=`echo $commit|awk -F'|' '{print $1}'|tr -d " "` STOPSNAP=`echo $commit|awk -F'|' '{print $2}'|tr -d " "` echo "STARTSNAP:"$STARTSNAP echo "STOPSNAP:"$STOPSNAP # 提取报表的开始与结束的snap #!/bin/bash PSQL="psql" pushd `dirname $0` array_index=1 for i in `$PSQL -t -U postgres -d mydb -c "with t as (select * from pgstatspack_snap order by snapid desc limit 4) select min(snapid) snapid from t union all select max(snapid) from t"` do if [ "$array_index" -eq 1 ] then STARTSNAP=$i else STOPSNAP=$i fi array_index=`expr $array_index + 1` done echo "STARTSNAP:"$STARTSNAP echo "STOPSNAP:"$STOPSNAP #生成报告 ./pgstatspack_report.sh -u postgres -d mydb -f /tmp/report/`date +%Y-%m-%d`.txt -D 1 #删除30天的文件 find /tmp/report/ -mtime +30 -type f -name *.txt | xargs rm -rf #自动发送邮件 #!/bin/bash pushd `dirname $0` # functions help_msg (){ echo "" echo "Usage:" echo " pgstatspack_report.sh [-u username] [-d database] [-f filename] [-h]" echo " Generates a statspack style report for a given postgres database" echo "" echo " -u username specifies the database user to connect to the database with" echo " -d database specifies the database to connect to" echo " -f filename specifies the filename where the report will be written" echo " -D days interval days from now " echo " -r receiver mail receiver" echo " -h prints this help message" echo "" exit 0 } while getopts "u:d:f:h:D:r:" flag do case $flag in u) PGUSER=$OPTARG ;; d) PGDB=$OPTARG ;; f) FILENAME=$OPTARG ;; D) INTERVAL_DAY=$OPTARG ;; r) MAIL_RECEIVER=$OPTARG ;; \?|h) help_msg ;; esac done #如果文件名不存在,则系统自动生成 if [ $FILENAME"x" == "x" ] then FILENAME=/tmp/report/PGStatspack-$PGDB-`date +%Y-%m-%d`.txt fi echo $FILENAME #生成报告 ./pgstatspack_report.sh -u $PGUSER -d $PGDB -f $FILENAME -D $INTERVAL_DAY #发送邮件 mail -s pgstatspack_report_`date +%Y-%m-%d` -a $FILENAME $MAIL_RECEIVER < /tmp/report/mail.tpl #删除30天前的文件 find /tmp/report/ -mtime +30 -type f -name *.txt | xargs rm -rf #mail.tpl 模板文件内容 Hello: This is the system mail of pgstatpack, please do not reply ! Best Regards! #测试 ./pgstatspack_report_auto.sh -u postgres -d mydb -D 1 -r example_email /opt/PostgreSQL/tools/pgstatspack/bin/pgstatspack_report_job.sh -u postgres -d dev -D 1 -r example_email #!/bin/bash #set -x # pgstatspack report # version 2.3 # initially by frits hoogland # enhanced by keith pierno # added help message, error handling, improved input methods # added object reports for inserts, deletes, updates, and table to index read # fixed divide by zero problem in the reports when objects are recreated # enhanced by uwe bartels # added stats for contrib module pg_stat_statements # added stats for bgwriter with formulas by greg smith # begin enhancements # 添加环境变量 source ~/.bash_profile source /etc/profile PSQL="psql" pushd `dirname $0` #获取当前执行文件的目录 # functions help_msg (){ echo "" echo "Usage:" echo " pgstatspack_report.sh [-u username] [-d database] [-f filename] [-h]" echo " Generates a statspack style report for a given postgres database" echo "" echo " -u username specifies the database user to connect to the database with" echo " -d database specifies the database to connect to" echo " -f filename specifies the filename where the report will be written" echo " -D interval days from now " echo " -h prints this help message" echo "" exit 0 } install_stats (){ $PSQL -U $1 -d $2 -c "\i ../sql/pgstatspack_create_tables.sql" $PSQL -U $1 -d $2 -c "\i ../sql/pgstatspack_create_snap.sql" echo "" echo "Statistics package install for database $2" echo "You need to create at least 2 snapshots before running this report." exit } # end functions while getopts "u:d:f:h:D" flag do case $flag in u) PGUSER=$OPTARG ;; d) PGDB=$OPTARG ;; f) FILENAME=$OPTARG ;; D) INTERVAL_DAY=$OPTARG ;; \?|h) help_msg ;; esac done # 获取用户输入的用户名,密码,文件名等 # if no user specified ask operator for username echo "$flag" $OPTIND $OPTARG if [ $PGUSER"x" == "x" ] then echo "Please specify a username: " read username PGUSER=$username fi # if no db specified present list if [ $PGDB"x" == "x" ] then array_index=1 valid_selection=0 for i in `$PSQL -t -U $PGUSER -c "\i ../sql/db_name.sql"` do db_array[$array_index]=$i array_index=`expr $array_index + 1` done while [ $valid_selection -eq "0" ] do counter=1 echo "List of available databases:" echo "" while [ $counter -lt $array_index ] do echo $counter ". "${db_array[$counter]} counter=`expr $counter + 1` done echo "" echo "Please select a number from the above list [ 1 - " `expr $counter - 1 `" ] " read db_selection if [ -z "$db_selection" ] ;then echo "Please choose the database." exit 1 elif [ `echo "$db_selection"|egrep -c '[^0-9]'` -gt 0 ];then echo "Please enter a number for the database." exit 1 elif [ "$db_selection" -lt '1' ] || [ "$db_selection" -ge $counter ];then echo "Please enter a valid number from the list." exit 1 else valid_selection=1 PGDB=${db_array[$db_selection]} fi done fi # validate that statspack tables exist for the given database and the user can login x=`$PSQL -t -U $PGUSER -d $PGDB -c "\i ../sql/pgstats_exist.sql"` if [ $x -eq "0" ] then echo "The statistics gathering package does not exist for the database: $PGDB" echo "" echo "Would you like to install the statistics package for $PGDB ? [y|n] " read install_answer case $install_answer in y|Y) install_stats "$PGUSER" "$PGDB" ;; n|N) echo "Cancelling report" exit;; *) echo "Invalid answer cancelling report" exit;; esac elif [ $x -lt "6" ] then echo "Previous install of statisics package was for database $PGDB is incomplete!" echo "" echo "Would you like to reinstall the statistics package for $PGDB ? [y|n] " read install_answer case install_answer in y|Y) install_stats "$PGUSER" "$PGDB" ;; n|N) echo "Cancelling report" exit;; *) echo "Invalid answer cancelling report" exit;; esac fi # end input enhancements # generate stats report #$PSQL --user $PGUSER --dbname $PGDB --quiet --command " #select * from pgstatspack_snap order by snapid desc; #" if [ $INTERVAL_DAY"x" == "x" ] then INTERVAL_DAY=`$PSQL --user $PGUSER --dbname $PGDB --quiet -t --command " select current_date-max(ts)::date +1 from pgstatspack_snap; "` fi commit=`$PSQL --user $PGUSER --dbname $PGDB --quiet -t --command " select min(snapid),max(snapid) from pgstatspack_snap where ts>now()- interval '${INTERVAL_DAY} day'; "` STARTSNAP=`echo $commit|awk -F'|' '{print $1}'|tr -d " "` STOPSNAP=`echo $commit|awk -F'|' '{print $2}'|tr -d " "` #printf "Enter start snapshot id : " #read STARTSNAP #printf "Enter stop snapshot id : " #read STOPSNAP if [ $FILENAME"x" == "x" ] then FILENAME=/tmp/pgstatreport_${PGDB}_${STARTSNAP}_${STOPSNAP}.txt fi echo "Using file name: $FILENAME" # heading printf "###########################################################################################################" | tee $FILENAME printf "\nPGStatspack version 2.3 \n" | tee -a $FILENAME printf "\n Hostname:`hostname` \n" | tee -a $FILENAME printf "\n IP:`ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}'` \n" | tee -a $FILENAME printf "###########################################################################################################\n\n" | tee -a $FILENAME printf "Snapshot information\n" | tee -a $FILENAME printf "Begin snapshot : \n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " select b.snapid, b.ts, b.description from pgstatspack_snap b where b.snapid=$STARTSNAP; " | tee -a $FILENAME printf "End snapshot :\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " select e.snapid, e.ts, e.description from pgstatspack_snap e where e.snapid=$STOPSNAP; " | tee -a $FILENAME printf "Seconds in snapshot: " | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --tuples-only --command " select EXTRACT(EPOCH FROM (e.ts-b.ts)) from pgstatspack_snap b, pgstatspack_snap e where b.snapid=$STARTSNAP and e.snapid=$STOPSNAP; " | tee -a $FILENAME printf "\nDatabase version\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " select version(); " | tee -a $FILENAME printf "Database information\n" $PSQL --user $PGUSER --dbname $PGDB --quiet --command " select current_database(), pg_size_pretty(pg_database_size(current_database())) as dbsize; " | tee -a $FILENAME printf "\nDatabase statistics\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT a.datname as database, round(CAST ( ((b.xact_commit-a.xact_commit)/(select EXTRACT(EPOCH FROM (d.ts-c.ts)) from pgstatspack_snap c, pgstatspack_snap d where c.snapid=$STARTSNAP and d.snapid=$STOPSNAP)) AS numeric) ,2) as tps, round(CAST ( (100*(b.blks_hit-a.blks_hit)/((b.blks_read-a.blks_read)+(b.blks_hit-a.blks_hit+1))) AS numeric) ,2) as hitrate, round(CAST ( (((b.blks_read-a.blks_read)+(b.blks_hit-a.blks_hit))/(select EXTRACT(EPOCH FROM (d.ts-c.ts)) from pgstatspack_snap c, pgstatspack_snap d where c.snapid=$STARTSNAP and d.snapid=$STOPSNAP)) AS numeric) ,2) as lio_ps, round(CAST ( ((b.blks_read-a.blks_read)/(select EXTRACT(EPOCH FROM (d.ts-c.ts)) from pgstatspack_snap c, pgstatspack_snap d where c.snapid=$STARTSNAP and d.snapid=$STOPSNAP)) as numeric),2) as pio_ps, round(CAST ( ((b.xact_rollback-a.xact_rollback)/(select EXTRACT(EPOCH FROM (d.ts-c.ts)) from pgstatspack_snap c, pgstatspack_snap d where c.snapid=$STARTSNAP and d.snapid=$STOPSNAP)) as numeric) ,2) as rollbk_ps FROM pgstatspack_database_v a, pgstatspack_database_v b WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND a.datname=b.datname ORDER BY tps desc; " | tee -a $FILENAME # get total tuples TUPLES_TOTAL=$( $PSQL --user $PGUSER --dbname $PGDB --tuples-only --quiet --command " SELECT 'aaa',SUM(((b.seq_tup_read-a.seq_tup_read)+(b.idx_tup_fetch-a.idx_tup_fetch))) as tup, SUM(((b.n_tup_ins-a.n_tup_ins)+(b.n_tup_ins-a.n_tup_ins))) as tup_ins, SUM(((b.n_tup_upd-a.n_tup_upd)+(b.n_tup_upd-a.n_tup_upd))) as tup_upd, SUM(((b.n_tup_del-a.n_tup_del)+(b.n_tup_del-a.n_tup_del))) as n_tup_del FROM pgstatspack_tables_v a join pgstatspack_tables_v b on a.table_name=b.table_name WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND ((b.seq_tup_read is not null) and (b.idx_tup_fetch is not null)) AND NOT ( (((b.seq_tup_read-a.seq_tup_read)+(b.idx_tup_fetch-a.idx_tup_fetch))=0) ); " | grep aaa | awk '{ printf "%d", $3 }' ) # report for table + index size changes printf "\nTop 20 tables ordered by table size changes\n"| tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT a.table_name as table, b.tbl_size-a.tbl_size as table_growth, b.idx_size-a.idx_size as index_growth FROM pgstatspack_tables_v a join pgstatspack_tables_v b on a.table_name=b.table_name WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP ORDER BY abs(b.tbl_size-a.tbl_size) desc limit 20; " | tee -a $FILENAME # new report metric to find tables that are not using or are missing indexes printf "\nTop 20 tables ordered by high table to index read ratio\n"| tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT a.table_name as table, 100*((b.seq_tup_read-a.seq_tup_read)+(b.idx_tup_fetch-a.idx_tup_fetch))/$TUPLES_TOTAL as system_read_pct, 100*(b.seq_tup_read-a.seq_tup_read)/((b.seq_tup_read-a.seq_tup_read)+(b.idx_tup_fetch-a.idx_tup_fetch)) as table_read_pct, 100*(b.idx_tup_fetch-a.idx_tup_fetch)/((b.seq_tup_read-a.seq_tup_read)+(b.idx_tup_fetch-a.idx_tup_fetch)) as index_read_pct FROM pgstatspack_tables_v a join pgstatspack_tables_v b on a.table_name=b.table_name WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND b.seq_tup_read >= a.seq_tup_read AND b.idx_tup_fetch >= a.idx_tup_fetch AND ((b.seq_tup_read is not null) and (b.idx_tup_fetch is not null)) AND NOT ( (((b.seq_tup_read-a.seq_tup_read)+(b.idx_tup_fetch-a.idx_tup_fetch))<=0) ) ORDER BY system_read_pct DESC, table_read_pct DESC limit 20; " | tee -a $FILENAME # added top 20 tables by insert printf "\nTop 20 tables ordered by inserts\n"| tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT a.table_name as table, (b.n_tup_ins-a.n_tup_ins) as table_inserts FROM pgstatspack_tables_v a join pgstatspack_tables_v b on a.table_name=b.table_name WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND b.n_tup_ins >= a.n_tup_ins ORDER BY table_inserts DESC limit 20; " | tee -a $FILENAME # added top 20 tables by update printf "\nTop 20 tables ordered by updates\n"| tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT a.table_name as table, (b.n_tup_upd-a.n_tup_upd) as table_updates FROM pgstatspack_tables_v a join pgstatspack_tables_v b on a.table_name=b.table_name WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND b.n_tup_upd >= a.n_tup_upd --group by table_updates, a.table_name ORDER BY table_updates DESC limit 20; " | tee -a $FILENAME # added top 20 tables by deletes printf "\nTop 20 tables ordered by deletes\n"| tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT a.table_name as table, (b.n_tup_del-a.n_tup_del) as table_deletes FROM pgstatspack_tables_v a join pgstatspack_tables_v b on a.table_name=b.table_name WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND b.n_tup_del >= a.n_tup_del --group by table_deletes, a.table_name ORDER BY table_deletes DESC limit 20; " | tee -a $FILENAME printf "\nTables ordered by percentage of tuples scanned\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT a.table_name as table, 100*((b.seq_tup_read-a.seq_tup_read)+(b.idx_tup_fetch-a.idx_tup_fetch))/$TUPLES_TOTAL as rows_read_pct, 100*(b.heap_blks_hit-a.heap_blks_hit)/((b.heap_blks_hit-a.heap_blks_hit)+((b.heap_blks_read-a.heap_blks_read))+1) as tab_hitrate, 100*(b.idx_blks_hit-a.idx_blks_hit)/((b.idx_blks_hit-a.idx_blks_hit)+((b.idx_blks_read-a.idx_blks_read))+1) as idx_hitrate, (b.heap_blks_read-a.heap_blks_read) as tab_read, (b.heap_blks_hit-a.heap_blks_hit) as tab_hit, (b.idx_blks_read-a.idx_blks_read) as idx_read, (b.idx_blks_hit-a.idx_blks_hit) as idx_hit FROM pgstatspack_tables_v a join pgstatspack_tables_v b on a.table_name=b.table_name WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND b.heap_blks_hit >= a.heap_blks_hit AND b.idx_blks_hit >= a.idx_blks_hit AND b.heap_blks_read >= a.heap_blks_read AND b.idx_blks_read >= a.idx_blks_read AND ((b.seq_tup_read is not null) and (b.idx_tup_fetch is not null)) AND NOT ( (((b.seq_tup_read-a.seq_tup_read)+(b.idx_tup_fetch-a.idx_tup_fetch))<=0) ) ORDER BY rows_read_pct DESC; " | tee -a $FILENAME printf "\nIndexes ordered by scans\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT a.index_name as index, a.table_name as table, (b.idx_scan-a.idx_scan) as scans, (b.idx_tup_read-a.idx_tup_read) as tup_read, (b.idx_tup_fetch-a.idx_tup_fetch) as tup_fetch, (b.idx_blks_read-a.idx_blks_read) as idx_blks_read, (b.idx_blks_hit-a.idx_blks_hit) as idx_blks_hit FROM pgstatspack_indexes_v a join pgstatspack_indexes_v b on a.index_name=b.index_name and a.table_name=b.table_name WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND NOT( ((b.idx_blks_read-a.idx_blks_read)<=0) and ((b.idx_blks_hit-a.idx_blks_hit)<=0) and ((b.idx_tup_read-a.idx_tup_read)<=0) and ((b.idx_tup_fetch-a.idx_tup_fetch)<=0) ) ORDER BY scans DESC; " | tee -a $FILENAME printf "\nSequences ordered by blks_read\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT a.sequence_name as sequence, (b.seq_blks_read-a.seq_blks_read) as blks_read, (b.seq_blks_hit-a.seq_blks_hit) as blks_hit FROM pgstatspack_sequences_v a join pgstatspack_sequences_v b on a.sequence_name=b.sequence_name WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND NOT ( ((b.seq_blks_read-a.seq_blks_read)=0) and ((b.seq_blks_hit-a.seq_blks_hit)=0)) ORDER BY blks_read DESC; " | tee -a $FILENAME printf "\nTop 20 SQL statements ordered by total_time\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT b.calls-coalesce(a.calls,0) as calls, (b.total_time-coalesce(a.total_time,0))::numeric(10,3) as total_time, ((b.total_time-coalesce(a.total_time,0))*100/sum.total_time)::numeric(10,2) as total_time_percent, b.rows-coalesce(a.rows,0) as rows, b.user_name as user, b.query as query FROM pgstatspack_statements_v a right join pgstatspack_statements_v b on a.user_name=b.user_name and a.query=b.query, ( select sum(sb.calls-sa.calls) as calls, sum(sb.total_time-sa.total_time) as total_time, sum(sb.rows-sa.rows) as rows from pgstatspack_statements sa right join pgstatspack_statements sb on sa.user_name_id=sb.user_name_id and sa.query_id=sb.query_id ) as sum WHERE a.snapid = $STARTSNAP and b.snapid = $STOPSNAP ORDER BY total_time desc LIMIT 20; " | tee -a $FILENAME printf "\nTop 20 user functions ordered by total_time\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT b.funcid, b.function_name, b.calls-coalesce(a.calls,0) as calls, (b.total_time-coalesce(a.total_time,0))::numeric(10,3) as total_time, (b.self_time-coalesce(a.self_time,0))::numeric(10,3) as self_time FROM pgstatspack_functions_v a right join pgstatspack_functions_v b on a.funcid=b.funcid WHERE a.snapid = $STARTSNAP and b.snapid = $STOPSNAP ORDER BY self_time desc LIMIT 20; " | tee -a $FILENAME printf "\nbackground writer stats\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT b.checkpoints_timed-a.checkpoints_timed as checkpoints_timed, b.checkpoints_req-a.checkpoints_req as checkpoints_req, b.buffers_checkpoint-a.buffers_checkpoint as buffers_checkpoint, b.buffers_clean-a.buffers_clean as buffers_clean, b.maxwritten_clean-a.maxwritten_clean as maxwritten_clean, b.buffers_backend-a.buffers_backend as buffers_backend, b.buffers_alloc-a.buffers_alloc as buffers_alloc FROM pgstatspack_bgwriter a, pgstatspack_bgwriter b WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP; " | tee -a $FILENAME printf "\nbackground writer relative stats\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT (b.checkpoints_timed-a.checkpoints_timed)*100/nullif(b.checkpoints_timed-a.checkpoints_timed+b.checkpoints_req-a.checkpoints_req,0)||'%' as checkpoints_timed, (extract(epoch from (sb.ts-sa.ts))/nullif(b.checkpoints_timed-a.checkpoints_timed+b.checkpoints_req-a.checkpoints_req,0)/60)::integer as minutes_between_checkpoint, (100*(b.buffers_checkpoint-a.buffers_checkpoint)/nullif((b.buffers_checkpoint-a.buffers_checkpoint)+(b.buffers_clean-a.buffers_clean)+(b.buffers_backend-a.buffers_backend),0))||'%' as buffers_checkpoint, (100*(b.buffers_clean-a.buffers_clean)/nullif((b.buffers_checkpoint-a.buffers_checkpoint)+(b.buffers_clean-a.buffers_clean)+(b.buffers_backend-a.buffers_backend),0))||'%' as buffers_clean, (100*(b.buffers_backend-a.buffers_backend)/nullif((b.buffers_checkpoint-a.buffers_checkpoint)+(b.buffers_clean-a.buffers_clean)+(b.buffers_backend-a.buffers_backend),0))||'%' as buffers_backend, ((((b.buffers_checkpoint-a.buffers_checkpoint)+(b.buffers_clean-a.buffers_clean)+(b.buffers_backend-a.buffers_backend))/nullif(extract(epoch from (sb.ts-sa.ts)),0))*8/1024)::numeric(10,3)||' MB/s' as total_writes, (((b.buffers_checkpoint-a.buffers_checkpoint)/nullif((b.checkpoints_timed-a.checkpoints_timed)+(b.checkpoints_req-a.checkpoints_req),0)*8/1024)::numeric(10,3))||' MB' as avg_checkpoint_write FROM pgstatspack_bgwriter a, pgstatspack_bgwriter b, pgstatspack_snap sa, pgstatspack_snap sb WHERE a.snapid=$STARTSNAP AND b.snapid=$STOPSNAP AND a.snapid=sa.snapid AND b.snapid=sb.snapid; " | tee -a $FILENAME printf "\nParameters\n" | tee -a $FILENAME $PSQL --user $PGUSER --dbname $PGDB --quiet --command " SELECT so.name as name, sa.setting as start_setting, so.setting as stop_setting, sa.source as source FROM pgstatspack_settings_v so LEFT OUTER JOIN pgstatspack_settings_v sa ON ( so.name=sa.name ) WHERE sa.snapid=$STARTSNAP AND so.snapid=$STOPSNAP; " | tee -a $FILENAME printf "\nThis report is saved as $FILENAME\n\n" popd