Após criar a rotina de VACUUM controlando o tempo de execução, post anterior, pensei em como poderia aplicar este método na manutenção dos índices de uma determinada base. Então as perguntas iniciais foram:
1 - O que eu queria com isso?
Precisava de uma rotina que realizasse a manutenção dos índices mais inchados da base, sendo que devido ao curto espaço de tempo disponível para a execução desta rotina, a mesma precisaria atingir as tabelas mais críticas da base.
2 - O que não poderia acontecer com isso?
- A rotina afetar a produção ou carga durante a produção;
- A rotina remover algum índice ativo;
- Prejudicar o plano de execução da base;
- Comprometer outra rotina de manutenção;
Com o risco calculado e um bom ambiente de homologação, foi criada uma rotina de reindexação que avalia o inchaço dos índices não PK das 15 tabelas com mais atualizações e exclusões de registros. Em resumo a rotina obtêm a DDL destes índices e um a um cria um índice temporário, após deleta o índice inchado e ao término atualiza as estatísticas destas tabelas.
Como o processo é transacional, como temos um controle de tempo(exemplo timeout é 6 horas da manhã) caso este controle de tempo mate a criação de índice o índice ainda inchado não é afetado.
Requisitos:
1 - A base alvo deve possuir a VIEW abaixo:
CREATE OR REPLACE VIEW bloat_objects AS SELECT current_database() AS current_database, sml.schemaname, sml.tablename, sml.reltuples::bigint AS reltuples, sml.relpages::bigint AS relpages, sml.otta, round( CASE WHEN sml.otta = 0::double precision THEN 0.0 ELSE sml.relpages::numeric / sml.otta::numeric END, 1) AS tbloat, CASE WHEN sml.relpages::double precision < sml.otta THEN 0::double precision ELSE sml.relpages::bigint::double precision - sml.otta END AS wastedpages, CASE WHEN sml.relpages::double precision < sml.otta THEN 0::numeric ELSE sml.bs * (sml.relpages::double precision - sml.otta)::bigint::numeric END AS wastedbytes, CASE WHEN sml.relpages::double precision < sml.otta THEN '0 bytes'::text ELSE (sml.bs::double precision * (sml.relpages::double precision - sml.otta))::bigint || ' bytes'::text END AS wastedsize, sml.iname, sml.ituples::bigint AS ituples, sml.ipages::bigint AS ipages, sml.iotta, round( CASE WHEN sml.iotta = 0::double precision OR sml.ipages = 0 THEN 0.0 ELSE sml.ipages::numeric / sml.iotta::numeric END, 1) AS ibloat, round( CASE WHEN sml.iotta = 0::double precision OR sml.ipages = 0 THEN 0.0 ELSE sml.ipages::numeric / sml.iotta::numeric END, 1) * 100::numeric AS perc_ibloat, CASE WHEN sml.ipages::double precision < sml.iotta THEN 0::double precision ELSE sml.ipages::bigint::double precision - sml.iotta END AS wastedipages, CASE WHEN sml.ipages::double precision < sml.iotta THEN 0::double precision ELSE sml.bs::double precision * (sml.ipages::double precision - sml.iotta) END AS wastedibytes, CASE WHEN sml.ipages::double precision < sml.iotta THEN '0 bytes'::text ELSE (sml.bs::double precision * (sml.ipages::double precision - sml.iotta))::bigint || ' bytes'::text END AS wastedisize FROM ( SELECT rs.schemaname, rs.tablename, cc.reltuples, cc.relpages, rs.bs, ceil(cc.reltuples * ((rs.datahdr + rs.ma::numeric - CASE WHEN (rs.datahdr % rs.ma::numeric) = 0::numeric THEN rs.ma::numeric ELSE rs.datahdr % rs.ma::numeric END)::double precision + rs.nullhdr2 + 4::double precision) / (rs.bs::double precision - 20::double precision)) AS otta, COALESCE(c2.relname, '?'::name) AS iname, COALESCE(c2.reltuples, 0::real) AS ituples, COALESCE(c2.relpages, 0) AS ipages, COALESCE(ceil(c2.reltuples * (rs.datahdr - 12::numeric)::double precision / (rs.bs::double precision - 20::double precision)), 0::double precision) AS iotta FROM ( SELECT foo.ma, foo.bs, foo.schemaname, foo.tablename, (foo.datawidth + (foo.hdr + foo.ma - CASE WHEN (foo.hdr % foo.ma) = 0 THEN foo.ma ELSE foo.hdr % foo.ma END)::double precision)::numeric AS datahdr, foo.maxfracsum * (foo.nullhdr + foo.ma - CASE WHEN (foo.nullhdr % foo.ma::bigint) = 0 THEN foo.ma::bigint ELSE foo.nullhdr % foo.ma::bigint END)::double precision AS nullhdr2 FROM ( SELECT s.schemaname, s.tablename, constants.hdr, constants.ma, constants.bs, sum((1::double precision - s.null_frac) * s.avg_width::double precision) AS datawidth, max(s.null_frac) AS maxfracsum, constants.hdr + (( SELECT 1 + count(*) / 8 FROM pg_stats s2 WHERE s2.null_frac <> 0::double precision AND s2.schemaname = s.schemaname AND s2.tablename = s.tablename)) AS nullhdr FROM pg_stats s, ( SELECT ( SELECT current_setting('block_size'::text)::numeric AS current_setting) AS bs, CASE WHEN "substring"(foo.v, 12, 3) = ANY (ARRAY['8.0'::text, '8.1'::text, '8.2'::text]) THEN 27 ELSE 23 END AS hdr, CASE WHEN foo.v ~ 'mingw32'::text THEN 8 ELSE 4 END AS ma FROM ( SELECT version() AS v) foo) constants GROUP BY s.schemaname, s.tablename, constants.hdr, constants.ma, constants.bs) foo) rs JOIN pg_class cc ON cc.relname = rs.tablename JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = rs.schemaname AND nn.nspname <> 'information_schema'::name LEFT JOIN pg_index i ON i.indrelid = cc.oid LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid) sml ORDER BY CASE WHEN sml.relpages::double precision < sml.otta THEN 0::numeric ELSE sml.bs * (sml.relpages::double precision - sml.otta)::bigint::numeric END DESC; ALTER TABLE bloat_objects OWNER TO postgres;
Estrutura da rotina:
1 - O path deve ser ajustado dentro da rotina para o path que utilizará;
2 - Deves criar dentro deste path as pastas: bin / log / var / lib / tmp.
Abaixo a rotina de reindexação(crie dentro do 'bin' com o nome 'reindex-maintenance-pgsql.pl'):
#!/usr/bin/perl #reindex-maintenance-pgsql # #Description: Rotina de manutenção de REINDEX para o PostgreSQL # #Author: # Gabriel Prestes (helkmut@gmail.com) # #07-31-2013 : Created use strict; use Getopt::Long; use POSIX; use File::Basename; use warnings; #-------------------------------------------------- # Setting environment #-------------------------------------------------- $ENV{"USER"}="root"; $ENV{"HOME"}="/root"; #-------------------------------------------------- # Global variables #-------------------------------------------------- our $name = basename($0); our $version = "1.2"; our $opt_path = "/opt/resources/reindex-maintenance-pgsql"; our $log_date = `/bin/date -I`; chomp($log_date); our $temp_log = "$opt_path/log/reindex-maintenance-pgsql-$log_date.log"; our $opt_props = "$opt_path/lib/maindb.props"; our ($opt_help, $opt_verbose, $opt_version); #-------------------------------------------------- # Program variables #-------------------------------------------------- #-------------------------------------------------- # Prop variables #-------------------------------------------------- our $opt_pguser; our $opt_pgport; our $opt_pgdb; our $opt_owner; our $opt_fim; #-------------------------------------------------------------------------------------- sub main { # --- Get Options --- # getoption(); # --- Init function vars ---# my $counter = 0; my $flagcontrol=0; my $rows=0; my $sqlquery; my $cmd; my @prop_split=(); my @props_array=(); my @tables=(); my @sqlcmd = (); # --- Verbose ---# logger("|PROGRAM OUT: Init agent|"); # --- Get props program --- # open (PROPS, "$opt_props") or error(); @props_array =; close(PROPS); foreach(@props_array){ chomp($_); @prop_split = split(/=/,$_); if($counter == 0){$opt_pguser = $prop_split[1];} if($counter == 1){$opt_pgport = $prop_split[1];} if($counter == 2){$opt_pgdb = $prop_split[1];} if($counter == 3){$opt_owner = $prop_split[1];} if($counter == 4){$opt_fim = $prop_split[1];} $counter++; } $counter=0; # --- Check and write pid --- # if(check_pid() == 0){ logger("|PROGRAM OUT: Another job in execution($opt_path/var/reindex-maintenance-pgsql.pid)|"); exit(1); } else { write_pid(); } # --- Rotate logs more than 15 days --- # logger("|PROGRAM OUT: LOGs - Search for more than 15 days old|"); $cmd=`\$\(which find\) $opt_path/log/* -name "*" -mtime +15 -exec \$\(which rm\) -rf {} \\; > /dev/null 2>&1`; # --- Get relations to reindex --- # logger("|PROGRAM OUT: Obtendo relacao de tabelas mais utilizadas com indices inchados|"); $sqlquery = "SELECT DISTINCT ON (tablename) tablename FROM bloat_objects WHERE (tablename IN ( SELECT relname FROM pg_stat_user_tables WHERE (n_tup_upd+n_tup_del) > 0 ORDER BY (n_tup_upd+n_tup_del) DESC LIMIT 30 )) AND perc_ibloat > 50::numeric ORDER BY tablename, perc_ibloat DESC;"; @sqlcmd = `/usr/bin/psql -U $opt_pguser -p $opt_pgport $opt_pgdb -q -c \"$sqlquery\"`; $flagcontrol+=$?; if($flagcontrol>0){ logger("|PROGRAM OUT: Nao pode obter lista de tabelas : falha de comunicacao com a instancia|"); exit_program(); } # --- Mount tables in array --- # foreach(@sqlcmd){ chomp($_); if($_ =~ m/^ (.+)$/g){ push(@tables,$1); } if($_ =~ m/^\((.+) row.+$/){ $rows=$1; } } my @sqlcmdaux = (); my $sqlindexquery; my $sqlin; my $sqlindexpart1; my $sqlindexpart2; my $sqlindexpart3; my $sqlindexpartnew = "idx_temp_maintenance"; trim($rows); if(@tables){ foreach(@tables){ chomp($_); trim($_); if($_ !~ "tablename"){ logger("|PROGRAM OUT: A tabela '$_' sera reindexada|"); foreach(@tables){ chomp($_); $sqlin .= "\'$_\',"; } chop($sqlin); } } } logger("|PROGRAM OUT: $rows tabelas para reindexar|"); if($rows==0){ logger("|PROGRAM OUT: OK - Rotina de reindexacao realizada com sucesso!|"); exit_program(); } my $time=`/bin/date +%H`; my $indexcount=0; chomp($time); # --- Build REINDEX command --- # logger("|PROGRAM OUT: Montando vetor de tabelas...|"); logger("|PROGRAM OUT: Obtendo relacao de indices...|"); $sqlquery = "SELECT REPLACE(Pg_get_indexdef(i.oid), 'INDEX ', 'INDEX CONCURRENTLY ') || ';' FROM pg_index x JOIN pg_class c ON c.oid = x.indrelid JOIN pg_class i ON i.oid = x.indexrelid LEFT JOIN pg_namespace n ON n.oid = c.relnamespace LEFT JOIN pg_tablespace t ON t.oid = i.reltablespace WHERE c.relkind = 'r'::\"char\" AND i.relkind = 'i'::\"char\" AND indisprimary IS FALSE AND c.relname IN($sqlin);"; @sqlcmd = `/usr/bin/psql -U $opt_pguser -p $opt_pgport $opt_pgdb -q -c \"$sqlquery\"`; logger("|PROGRAM OUT: Retorno de DDL criacao dos indices:|"); foreach(@sqlcmd){ chomp($_); logger("$_"); } # --- Drop idx_temp_maintenance if exists --- # logger("|PROGRAM OUT: Drop $sqlindexpartnew if exists|"); @sqlcmdaux = `/usr/bin/psql -U $opt_pguser -p $opt_pgport $opt_pgdb -q -c \"DROP INDEX IF EXISTS $sqlindexpartnew\"`; $flagcontrol += $?; # --- Run reindex --- # foreach(@sqlcmd){ $sqlindexquery = ""; $sqlindexquery = $_; if($sqlindexquery =~ m/^ (CREATE.+CONCURRENTLY) (.+) (ON.+)$/){ $sqlindexpart1=$1; $sqlindexpart2=$2; $sqlindexpart3=$3; # --- Time check --- # $time=`/bin/date +%H`; chomp($time); if($time>=$opt_fim){ logger("|PROGRAM OUT: Recriacao do indice abortado em funcao do horario: $time|"); next; } else { logger("|PROGRAM OUT: Horario verificado nao excede gatilho: $time|"); $indexcount++; } logger("|PROGRAM OUT: Recriando indice: $sqlindexpart2|"); logger("$sqlindexpart1 $sqlindexpartnew $sqlindexpart3"); @sqlcmdaux = `/usr/bin/psql -U $opt_pguser -p $opt_pgport $opt_pgdb -q -c \"$sqlindexpart1 $sqlindexpartnew $sqlindexpart3\"`; $flagcontrol += $?; if($flagcontrol>0){next;} logger("DROP INDEX $sqlindexpart2;"); @sqlcmdaux = `/usr/bin/psql -U $opt_pguser -p $opt_pgport $opt_pgdb -q -c \"BEGIN;DROP INDEX $sqlindexpart2;ALTER INDEX $sqlindexpartnew RENAME TO $sqlindexpart2;ALTER INDEX $sqlindexpart2 OWNER TO $opt_owner;COMMIT;\"`; $flagcontrol += $?; } } if($indexcount==0){ logger("|PROGRAM OUT: ALERTA - Rotina abortada em funcao do horario: $time|"); exit_program(); } # --- ANALYZE tables --- # foreach(@tables){ trim($_); if($_ !~ "tablename"){ chomp($_); logger("|PROGRAM OUT: Atualizando as estatisticas da tabela '$_'|"); @sqlcmdaux = `/usr/bin/psql -U $opt_pguser -p $opt_pgport $opt_pgdb -q -c \"ANALYZE $_;\"`; $flagcontrol += $?; } } # ---> Avaliar necessidade de resetar estatísticas da base # logger("|PROGRAM OUT: Resetando as estatisticas da base|"); # @sqlcmdaux = `/usr/bin/psql -U $opt_pguser -p $opt_pgport $opt_pgdb -q -c \"SELECT pg_stat_reset();\"`; # $flagcontrol += $?; # --- Threshoulds --- # if($flagcontrol>0){ logger("|PROGRAM OUT: ERRO - Rotina de reindexacao finalizou com erros($flagcontrol) verifique o mais rapido possivel|"); } else { logger("|PROGRAM OUT: OK - Rotina de reindexacao realizada com sucesso!|"); } exit_program(); } #-------------------------------------------------------------------------------------- sub getoption { Getopt::Long::Configure('bundling'); GetOptions( 'V|version' => \$opt_version, 'h|help' => \$opt_help, 'v|verbose=i' => \$opt_verbose, ); if($opt_help){ printHelp(); exit_program(); } if($opt_version){ print "$name - '$version'\n"; exit_program(); } } #-------------------------------------------------------------------------------------- sub logger { return(0) if (not defined $opt_verbose); my $msg = shift (@_); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time); $wday++; $yday++; $mon++; $year+=1900; $isdst++; if ($opt_verbose == 0){ print "$msg\n"; } else { open(LOG, ">>$temp_log") or error(); printf LOG ("%02i/%02i/%i - %02i:%02i:%02i => %s\n",$mday,$mon,$year,$hour,$min,$sec,$msg); close(LOG); } } #-------------------------------------------------------------------------------------- sub printHelp { my $help = <<'HELP'; Thanks for use Reindex Maintenance PGSQL. API required: strict; Getopt::Long; POSIX; File::Basename; warnings; Agent binary : bin/reindex-maintenance-pgsql.pl & Configuration Agent in : lib/maindb.props Support : helkmut@gmail.com Salmo 91: "Direi do Senhor: Não temerás os terrores da noite, nem a seta que voe de dia, nem peste que anda na escuridão, nem mortandade que assole ao meio-dia." HELP system("clear"); print $help; } #-------------------------------------------------------------------------------------- sub error { print "|ERROR - Unexpected return - contact support|\n"; exit_program(); } #-------------------------------------------------------------------------------------- sub trim($) { my $string = shift; $string =~ s/^\s+//; $string =~ s/\s+$//; return $string; } #-------------------------------------------------------------------------------------- sub write_pid { my $cmd; $cmd=`\$\(which touch\) $opt_path/var/reindex-maintenance-pgsql.pid`; return 1; } #-------------------------------------------------------------------------------------- sub check_pid { if(-e "$opt_path/var/reindex-maintenance-pgsql.pid"){ return 0; } else { return 1; } } #-------------------------------------------------------------------------------------- sub exit_program { my $cmd; $cmd=`\$\(which rm\) -rf $opt_path/var/reindex-maintenance-pgsql.pid`; exit; } #-------------------------------------------------------------------------------------- &main ##Ignore o ' ' se existir no final, é um erro de formatação do post.
Arquivo de configuração(crie dentro do 'lib' com o nome 'maindb.props'):
opt_pguser=postgres opt_pgport=5432 opt_pgdb=postgres opt_owner=postgres opt_fim=06 # --- Additional info --- # opt_pguser - > Login role opt_pgport -> Instance port opt_pgdb -> Database connect opt_owner -> Owner index opt_fim -> Time abort # --- Additional info --- #
Arquivo de controle de tempo(crie dentro do 'bin' com nome 'reindex-controltime-pgsql.pl'):
#!/usr/bin/perl #reindex-controltime-pgsql # #Description: Rotina de controle de manutenção de REINDEX para o PostgreSQL # #Author: # Gabriel Prestes (helkmut@gmail.com) # #08-09-2013 : Created use strict; use Getopt::Long; use POSIX; use File::Basename; use warnings; #-------------------------------------------------- # Setting environment #-------------------------------------------------- $ENV{"USER"}="root"; $ENV{"HOME"}="/root"; #-------------------------------------------------- # Global variables #-------------------------------------------------- our $name = basename($0); our $version = "0.1"; our $opt_path = "/opt/resources/reindex-maintenance-pgsql"; our $log_date = `/bin/date -I`; chomp($log_date); our $temp_log = "$opt_path/log/reindex-controltime-pgsql-$log_date.log"; our $opt_props = "$opt_path/lib/maindb.props"; our ($opt_help, $opt_verbose, $opt_version); #-------------------------------------------------- # Program variables #-------------------------------------------------- #-------------------------------------------------- # Prop variables #-------------------------------------------------- our $opt_pguser; our $opt_pgport; our $opt_pgdb; our $opt_fim; #-------------------------------------------------------------------------------------- sub main { # --- Get Options --- # getoption(); # --- Init function vars ---# my $counter = 0; my $flagcontrol=0; my $rows=0; my $sqlquery; my $cmd; my @prop_split=(); my @props_array=(); my @command=(); my @sqlcmd = (); # --- Verbose ---# logger("|PROGRAM OUT: Init agent|"); # --- Get props program --- # open (PROPS, "$opt_props") or error(); @props_array =; close(PROPS); foreach(@props_array){ chomp($_); @prop_split = split(/=/,$_); if($counter == 0){$opt_pguser = $prop_split[1];} if($counter == 1){$opt_pgport = $prop_split[1];} if($counter == 2){$opt_pgdb = $prop_split[1];} if($counter == 4){$opt_fim = $prop_split[1];} $counter++; } $counter=0; # --- Check and write pid --- # if(check_pid() == 0){ logger("|PROGRAM OUT: Another job in execution($opt_path/var/reindex-controltime-pgsql.pid)|"); exit(1); } else { write_pid(); } # --- Rotate logs more than 15 days --- # logger("|PROGRAM OUT: LOGs - Search for more than 15 days old|"); $cmd=`\$\(which find\) $opt_path/log/* -name "*" -mtime +15 -exec \$\(which rm\) -rf {} \\; > /dev/null 2>&1`; # --- Get relations to reindex --- # logger("|PROGRAM OUT: Obtendo relacao de reindex em execucao|"); $sqlquery = "SELECT pg_stat_activity.procpid as processo FROM pg_stat_activity WHERE pg_stat_activity.current_query LIKE 'CREATE INDEX CONCURRENTLY idx_temp_maintenance%';"; @sqlcmd = `/usr/bin/psql -U $opt_pguser -p $opt_pgport $opt_pgdb -q -c \"$sqlquery\"`; $flagcontrol+=$?; if($flagcontrol>0){ logger("|PROGRAM OUT: Nao pode obter lista de indices : falha de comunicacao com a instancia|"); exit_program(); } # --- Mount tables in array --- # foreach(@sqlcmd){ chomp($_); if($_ =~ m/^ (.+)$/g){ push(@command,$1); } if($_ =~ m/^\((.+) row.+$/){ $rows=$1; } } my @sqlcmdaux = (); trim($rows); if(@command){ foreach(@command){ chomp($_); if($_ !~ m/^proces.+$/){ trim($_); logger("|PROGRAM OUT: O processo$_ de recriacao do indice sera cancelado|"); @sqlcmd = `/usr/bin/psql -U $opt_pguser -p $opt_pgport $opt_pgdb -q -c \"SELECT pg_cancel_backend($_)\"`; } } } logger("|PROGRAM OUT: $rows reindex cancelado(s)|"); if($rows==0){ logger("|PROGRAM OUT: OK - Rotina de controle finalizada sem cancelamento de backends!|"); exit_program(); } # --- Threshoulds --- # logger("|PROGRAM OUT: OK - Rotina de controle finalizada com sucesso!|"); exit_program(); } #-------------------------------------------------------------------------------------- sub getoption { Getopt::Long::Configure('bundling'); GetOptions( 'V|version' => \$opt_version, 'h|help' => \$opt_help, 'v|verbose=i' => \$opt_verbose, ); if($opt_help){ printHelp(); exit_program(); } if($opt_version){ print "$name - '$version'\n"; exit_program(); } } #-------------------------------------------------------------------------------------- sub logger { return(0) if (not defined $opt_verbose); my $msg = shift (@_); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time); $wday++; $yday++; $mon++; $year+=1900; $isdst++; if ($opt_verbose == 0){ print "$msg\n"; } else { open(LOG, ">>$temp_log") or error(); printf LOG ("%02i/%02i/%i - %02i:%02i:%02i => %s\n",$mday,$mon,$year,$hour,$min,$sec,$msg); close(LOG); } } #-------------------------------------------------------------------------------------- sub printHelp { my $help = <<'HELP'; Thanks for use Reindex Controltime PGSQL. API required: strict; Getopt::Long; POSIX; File::Basename; warnings; Agent binary : bin/reindex-controltime-pgsql.pl & Configuration Agent in : lib/maindb.props Support : helkmut@gmail.com "Cordeiro de Deus, retirai os pecados do mundo, tende piedade de nós!" HELP system("clear"); print $help; } #-------------------------------------------------------------------------------------- sub error { print "|ERROR - Unexpected return - contact support|\n"; exit_program(); } #-------------------------------------------------------------------------------------- sub trim($) { my $string = shift; $string =~ s/^\s+//; $string =~ s/\s+$//; return $string; } #-------------------------------------------------------------------------------------- sub write_pid { my $cmd; $cmd=`\$\(which touch\) $opt_path/var/reindex-controltime-pgsql.pid`; return 1; } #-------------------------------------------------------------------------------------- sub check_pid { if(-e "$opt_path/var/reindex-controltime-pgsql.pid"){ return 0; } else { return 1; } } #-------------------------------------------------------------------------------------- sub exit_program { my $cmd; $cmd=`\$\(which rm\) -rf $opt_path/var/reindex-controltime-pgsql.pid`; exit; } #-------------------------------------------------------------------------------------- &main ##Ignore o ' ' se existir no final, é um erro de formatação do post.
Feito isto, precisarás de dois jobs no crontab ou no pgAgent, o da rotina de reindexação que deve por exemplo iniciar meia-noite e outro job com o controle de execução que deve ser agendado para o horário em que quer abortar a rotina, exemplo 6 horas da manhã.
Exemplo de execução no pgAgent:
1 - Crie um job do tipo manutenção que executará um 'BATCH' e não 'SQL';
2 - Agende para a data e horário desejado;
3 - Na definição do passo coloque '/opt/resources/reindex-maintenance-pgsql/bin/reindex-controltime-pgsql.pl -v 1';
Faça a mesma ação para o outro job de reindexação, deixando a definição como '/opt/resources/reindex-maintenance-pgsql/bin/reindex-maintenance-pgsql.pl -v 1'.
Explicação sobre os parâmetros de configuração:
opt_pguser=postgres -> Usuário do PostgreSQL que executará a rotina
opt_pgport=5432 -> Porta da instância
opt_pgdb=postgres -> Database da instância onde a rotina será executada
opt_owner=postgres -> Dono dos índices recriados na rotina
opt_fim=06 -> Tempo estabelecido para finalizar a rotina
Então você se pergunta:
Porque um programa auxiliar para terminar a rotina de reindexação se a mesma já possui este controle internamente?
A resposta será, caso a rotina esteja criando um índice a mesma continuará em execução até finalizar essa criação, com o programa auxiliar o backend onde a criação está ocorrendo é cancelado e o índice temporário que está sendo criado é invalidado.
Análise da rotina:
Um log exemplo de execução da rotina abaixo. Lembrando que os logs já são rotacionados, mantendo somente os últimos 15 dias.
Controle de execução:
20/08/2013 - 06:30:01 => |PROGRAM OUT: Init agent| 20/08/2013 - 06:30:01 => |PROGRAM OUT: LOGs - Search for more than 15 days old| 20/08/2013 - 06:30:01 => |PROGRAM OUT: Obtendo relacao de reindex em execucao| 20/08/2013 - 06:30:01 => |PROGRAM OUT: 0 reindex cancelado(s)| 20/08/2013 - 06:30:01 => |PROGRAM OUT: OK - Rotina de controle finalizada sem cancelamento de backends!|
Rotina de reindexação:
17/08/2013 - 00:01:03 => |PROGRAM OUT: Init agent| 17/08/2013 - 00:01:03 => |PROGRAM OUT: LOGs - Search for more than 15 days old| 17/08/2013 - 00:01:03 => |PROGRAM OUT: Obtendo relacao de tabelas mais utilizadas com indices inchados| 17/08/2013 - 00:01:03 => |PROGRAM OUT: A tabela 'teste' sera reindexada| 17/08/2013 - 00:01:03 => |PROGRAM OUT: 1 tabelas para reindexar| 17/08/2013 - 00:01:03 => |PROGRAM OUT: Montando vetor de tabelas...| 17/08/2013 - 00:01:03 => |PROGRAM OUT: Obtendo relacao de indices...| 17/08/2013 - 00:01:03 => |PROGRAM OUT: Retorno de DDL criacao dos indices:| 17/08/2013 - 00:01:03 => ?column? 17/08/2013 - 00:01:03 => ------------------------------------------------------------------------------------------------------------------------------- 17/08/2013 - 00:01:03 => CREATE INDEX CONCURRENTLY idx_teste_cli ON teste USING btree (cli); 17/08/2013 - 00:01:03 => CREATE INDEX CONCURRENTLY idx_teste_clo ON teste USING btree (clo); 17/08/2013 - 00:01:03 => (2 rows) 17/08/2013 - 00:01:03 => 17/08/2013 - 00:01:03 => |PROGRAM OUT: Drop idx_temp_maintenance if exists| 17/08/2013 - 00:01:03 => |PROGRAM OUT: Horario verificado nao excede gatilho: 00| 17/08/2013 - 00:01:03 => |PROGRAM OUT: Recriando indice: idx_teste_cli | 17/08/2013 - 00:01:03 => CREATE INDEX CONCURRENTLY idx_temp_maintenance ON teste USING btree (cli); 17/08/2013 - 00:02:03 => DROP INDEX idx_teste_cli; 17/08/2013 - 00:02:04 => |PROGRAM OUT: Horario verificado nao excede gatilho: 00| 17/08/2013 - 00:02:04 => |PROGRAM OUT: Recriando indice: idx_teste_clo | 17/08/2013 - 00:02:04 => CREATE INDEX CONCURRENTLY idx_temp_maintenance ON teste USING btree (clo); 17/08/2013 - 00:02:06 => DROP INDEX idx_teste_clo ; 17/08/2013 - 00:02:24 => |PROGRAM OUT: Atualizando as estatisticas da tabela 'teste'| 17/08/2013 - 00:02:45 => |PROGRAM OUT: Resetando as estatisticas da base| 17/08/2013 - 00:02:45 => |PROGRAM OUT: OK - Rotina de reindexacao realizada com sucesso!|
Nenhum comentário:
Postar um comentário