REINDEX — reconstrói índices
REINDEX [ (opção[, ...] ) ] { INDEX | TABLE | SCHEMA } [ CONCURRENTLY ]nomeREINDEX [ (opção[, ...] ) ] { DATABASE | SYSTEM } [ CONCURRENTLY ] [nome] ondeopçãopode ser uma entre: CONCURRENTLY [booleano] TABLESPACEnovo_espaço_de_tabelasVERBOSE [booleano]
O comando REINDEX reconstrói o índice usando os
dados armazenados na tabela do índice, substituindo a cópia antiga
do índice.
Existem vários cenários nos quais usar REINDEX:
O índice está corrompido, não contendo mais dados válidos.
Embora em teoria isto nunca deva acontecer, na prática, os índices
podem ser corrompidos devido a bugs de software ou falhas de hardware.
O comando REINDEX fornece um método de recuperação.
O índice tornou-se “inchado”, ou seja, contém muitas
páginas vazias, ou quase vazias.
Isto pode ocorrer com índices Árvore-B no
PostgreSQL sob certos padrões de acesso
incomuns.
O comando REINDEX fornece uma maneira de reduzir
o consumo de espaço do índice escrevendo uma nova versão do índice
sem as páginas mortas.
Veja Reindexação de rotina para obter mais informações.
Se foi alterado um parâmetro de armazenamento (como o fator de preenchimento) para o índice, e se deseja garantir que a alteração tenha efeito total.
Se a construção de um índice falhar com a opção
CONCURRENTLY, este índice será deixado como
“inválido”.
Estes índices são inúteis, mas pode ser conveniente usar
REINDEX para reconstruí-los.
Note que apenas REINDEX INDEX pode
executar a construção concorrente de um índice inválido.
INDEX
Recria o índice especificado.
Esta forma de REINDEX não pode ser executada
dentro de um bloco de transação, quando usada com um índice
particionado.
TABLE
Recria todos os índices da tabela especificada.
Se a tabela tiver uma tabela “TOAST” secundária,
ela também será reindexada.
Esta forma de REINDEX não pode ser executada
dentro de um bloco de transação, quando usada com uma tabela
particionada.
SCHEMA
Recria todos os índices do esquema especificado.
Se uma tabela desse esquema tiver uma tabela “TOAST”
secundária, ela também será reindexada.
Índices em catálogos do sistema compartilhados também são processados.
Esta forma de REINDEX não pode ser executada
dentro de um bloco de transação.
DATABASE
Recria todos os índices no banco de dados corrente,
exceto os catálogos do sistema.
Os índices dos catálogos do sistema não são processados.
Esta forma do comando REINDEX não pode ser
executada dentro de um bloco de transação.
SYSTEM
Recria todos os índices nos catálogos do sistema no banco de dados
corrente.
Os índices em catálogos do sistema compartilhados são incluídos.
Os índices em tabelas do usuário não são processados.
Esta forma do comando REINDEX não pode ser
executada dentro de um bloco de transação.
nome
O nome do índice, tabela ou banco de dados específico a ser reindexado.
Os nomes de índices e tabelas podem ser qualificados pelo esquema.
No momento, REINDEX DATABASE e
REINDEX SYSTEM só podem reindexar o banco de
dados corrente, sendo o parâmetro opcional, devendo corresponder
ao nome do banco de dados corrente.
CONCURRENTLYQuando esta opção é usada, o PostgreSQL irá reconstruir o índice sem obter nenhum bloqueio que impeça inserções, atualizações ou exclusões simultâneas na tabela; enquanto uma reconstrução de índice padrão bloqueia as escritas (mas não as leituras) na tabela até que termine. Há várias advertências a serem observadas ao usar esta opção — veja Reconstrução concorrente de índices abaixo.
Para tabelas temporárias, o comando REINDEX
é sempre não concorrente, porque nenhuma outra sessão pode
acessá-las, e a reindexação não concorrente é mais econômica.
TABLESPACEEspecifica que os índices serão reconstruídos em um novo espaço de tabelas.
VERBOSE
Gera um relatório de progresso no nível INFO
enquanto cada índice é reindexado.
booleano
Especifica se a opção selecionada deve ser ativada ou desativada.
Pode ser escrito TRUE, ON, ou
1 para ativar a opção, e FALSE,
OFF, ou 0 para desativá-la.
O valor booleano
também pode ser omitido, caso em que é assumido o valor
TRUE.
novo_espaço_de_tabelasO espaço de tabelas onde os índices serão reconstruídos.
Havendo suspeita de corrupção de um índice em uma tabela de usuário,
pode-se simplesmente reconstruir este índice, ou todos os índices da
tabela, usando os comandos REINDEX INDEX, ou
REINDEX TABLE.
As coisas são mais difíceis quando é necessário se recuperar da
corrupção de um índice em uma tabela do sistema.
Neste caso, é importante que o próprio sistema não tenha utilizado
nenhum dos índices suspeitos.
(De fato, neste tipo de cenário, pode-se descobrir que os processos
do servidor estão travando imediatamente na inicialização, devido à
dependência de índices corrompidos.)
Para recuperar com segurança, o servidor deve ser iniciado com a
opção -P, que impede o uso de índices para
procuras nos catálogos do sistema.
Uma maneira de fazer isto é parar o servidor, e iniciar o servidor
PostgreSQL de usuário único com a opção
-P incluída na linha de comando.
Então, pode ser executado REINDEX DATABASE,
REINDEX SYSTEM, REINDEX TABLE,
ou REINDEX INDEX, dependendo de quanto se deseja
reconstruir.
Em caso de dúvida, deve ser usado REINDEX SYSTEM
para selecionar a reconstrução de todos os índices do sistema no
banco de dados.
Em seguida, sair da sessão de servidor de usuário único, e reiniciar
o servidor normalmente.
Veja a página de referência do postgres para
obter mais informações sobre como interagir com a interface de
servidor de usuário único.
Como alternativa, pode ser iniciada uma sessão normal do servidor com
a opção -P incluída em suas opções de linha de comando.
O método para fazer isto varia entre clientes, mas em todos os
clientes baseados na libpq é possível
definir a variável de ambiente PGOPTIONS como
-P antes de iniciar o cliente.
Note que, embora este método não exija o bloqueio de outros clientes,
ainda pode ser prudente impedir que outros usuários conectem ao
banco de dados danificado até que os reparos sejam concluídos.
O comando REINDEX é semelhante a excluir e recriar
o índice, onde o conteúdo do índice é reconstruído a partir do zero.
Entretanto, as considerações de bloqueio são bastante diferentes.
O comando REINDEX bloqueia escritas, mas não
leituras da tabela associada do índice.
Ele também requer um bloqueio ACCESS EXCLUSIVE
no índice específico que está sendo processado, o que irá bloquear
as leituras que tentarem usar este índice.
Em particular, o planejador de consultas tenta obter um bloqueio
ACCESS SHARE em todos os índices da tabela,
independentemente da consulta e, portanto, o comando
REINDEX bloqueia praticamente todas as consultas,
exceto algumas consultas preparadas cujo plano foi armazenado em
cache e que não usam este índice
específico.
Em contraste, o comando DROP INDEX obtém
momentaneamente um bloqueio ACCESS EXCLUSIVE
na tabela associada, bloqueando escritas e leituras.
O comando CREATE INDEX subsequente bloqueia as
escritas, mas não as leituras; como o índice ainda não existe,
nenhuma leitura tentará usá-lo, significando que não haverá bloqueio,
mas as leituras podem ser forçadas a realizar varreduras sequenciais
dispendiosas.
Enquanto o comando REINDEX estiver em execução,
o search_path será temporariamente mudado para
pg_catalog, pg_temp.
A reindexação de um único índice ou tabela requer o privilégio
MAINTAIN na tabela.
Note que o comando REINDEX em um índice ou tabela
particionada requer o privilégio MAINTAIN
na tabela particionada, ignorando as verificações de privilégios
ao processar as partições individuais.
Reindexar um esquema ou banco de dados requer ser o dono desse esquema
ou banco de dados, ou ter privilégios de função de banco de dados
pg_maintain.
Note especificamente que, dessa forma, é possível que usuários sem
privilégios de superusuário reconstruam índices de tabelas
pertencentes a outros usuários.
Entretanto, como uma exceção especial,
REINDEX DATABASE, REINDEX SCHEMA,
e REINDEX SYSTEM irão pular os índices nos
catálogos compartilhados, a menos que o usuário tenha o privilégio
MAINTAIN no catálogo.
A reindexação de índices particionados, ou tabelas particionadas,
tem suporte com REINDEX INDEX ou
REINDEX TABLE, respectivamente.
Cada partição da relação particionada especificada é reindexada
em uma transação separada.
Estes comandos não podem ser usados dentro de um bloco de transação
ao trabalhar em uma tabela ou índice particionado.
Ao usar a cláusula TABLESPACE com o comando
REINDEX em um índice ou tabela particionada,
apenas as referências a espaço de tabelas das partições folha
são atualizadas.
Como os índices particionados não são atualizados, se recomenda usar
neles ALTER TABLE ONLY em separado, para que
quaisquer novas partições anexadas herdem o novo espaço de tabelas.
Em caso de falha, pode não ter sido movido todos os índices para
o novo espaço de tabelas.
Executar novamente o comando reconstruirá todas as partições folha
e moverá os índices não processados anteriormente para o novo
espaço de tabelas.
Se for usado SCHEMA, DATABASE ou
SYSTEM com TABLESPACE,
as relações do sistema serão ignoradas, e será gerado um único
WARNING.
Os índices nas tabelas TOAST são reconstruídos,
mas não são movidos para o novo espaço de tabelas.
A reconstrução de um índice pode interferir na operação regular do banco de dados. Normalmente, o PostgreSQL bloqueia contra escritas a tabela cujo índice é reconstruído, e executa a construção inteira do índice em uma única varredura da tabela. As demais transações ainda podem ler a tabela, mas se tentarem inserir, atualizar ou excluir linhas na tabela, elas serão bloqueadas até que a reconstrução do índice esteja concluída. Isto pode provocar um impacto importante, se o sistema for um banco de dados de produção ativo. Tabelas muito grandes podem levar muitas horas para serem indexadas e, mesmo em tabelas menores, a reconstrução do índice pode bloquear escrever por períodos inaceitavelmente longos para um sistema em produção.
O PostgreSQL oferece suporte à
reconstrução de índices com bloqueio mínimo de escrita.
Este método é chamado especificando a opção
CONCURRENTLY no comando
REINDEX.
Quando esta opção é usada, o PostgreSQL
deve executar duas varreduras da tabela para cada índice que precisa
ser reconstruído, e aguardar o término de todas as transações
existentes que poderiam potencialmente usar o índice.
Este método requer mais trabalho total do que a reconstrução de
índice padrão, levando muito mais tempo para ser concluído, porque
precisa aguardar pelas transações não concluídas que podem modificar
o índice.
Entretanto, como permite que as operações normais prossigam enquanto
o índice está sendo reconstruído, este método é útil para a
reconstrução de índices em um ambiente de produção.
Obviamente, a carga extra de CPU e E/S imposta pela recriação do
índice pode retardar outras operações.
As etapas a seguir ocorrem em uma reindexação concorrente. Cada etapa é executada em uma transação separada. Havendo vários índices a serem reconstruídos, cada etapa percorrerá todos os índices antes de passar para a próxima etapa.
Uma nova definição de índice transitória é adicionada ao catálogo
pg_index.
Esta definição será usada para substituir a antiga definição do
índice.
É obtido o bloqueio SHARE UPDATE EXCLUSIVE
no nível da sessão nos índices que estão sendo reindexados,
bem como em suas tabelas associadas, para evitar qualquer
modificação de esquema durante o processamento.
É realizada uma primeira passagem para construir o índice para
cada novo índice.
Após o índice ser construído, seu sinalizador
pg_index.indisready é alterado para
“true”, para torná-lo pronto para inserções,
tornando-o visível para as outras sessões assim que a transação
que executou a construção esteja finalizada.
Esta etapa é realizada em uma transação separada para cada índice.
Em seguida, uma segunda passagem é executada para adicionar as tuplas que foram adicionadas durante a execução da primeira passagem. Esta etapa também é realizada em uma transação separada para cada índice.
Todas as restrições que se referem ao índice são alteradas para
se referir à nova definição do índice, e os nomes dos índices
são alterados.
Neste ponto, pg_index.indisvalid é alterado
para “true” para o novo índice, e para
“false” para o antigo, e uma invalidação de
cache é feita, fazendo com que
todas as sessões que faziam referência ao índice antigo sejam
invalidadas.
Os índices antigos têm pg_index.indisready
mudado para “false”, para evitar novas inserções de
tuplas, após aguardar a execução das consultas que possam
fazer referência ao índice antigo serem concluídas.
Os índices antigos são removidos.
Os bloqueios de sessão SHARE UPDATE EXCLUSIVE
para os índices e a tabela são liberados.
Se ocorrer um problema durante a reconstrução dos índices, como uma
violação de unicidade em um índice de unicidade, o comando
REINDEX irá falhar, mas deixará para trás um novo
índice “inválido”, além do anterior pré-existente.
Este índice será ignorado para fins de consulta, porque pode estar
incompleto; entretanto, ainda consumirá sobrecarga de atualização.
O meta-comando \d do psql
irá mostrar este índice como INVALID:
postgres=# \d tab
Table "public.tab"
Column | Type | Modifiers
--------+---------+-----------
col | integer |
Indexes:
"idx" btree (col)
"idx_ccnew" btree (col) INVALID
Se o índice marcado como INVALID tiver o sufixo
_ccnew, então corresponde ao índice transitório
criado durante a operação concorrente, e o método de recuperação
recomendado é removê-lo usando DROP INDEX, e
depois tentado REINDEX CONCURRENTLY novamente.
Se o índice inválido tiver o sufixo _ccold, ele
corresponde ao índice original que não pôde ser removido;
o método de recuperação recomendado é apenas remover o referido
índice, porque a reconstrução adequada foi bem-sucedida.
Pode ser adicionado um número diferente de zero ao sufixo dos nomes
de índice inválidos para mantê-los únicos, como por exemplo
_ccnew1, _ccold2, etc.
As construções de índices regulares permitem que ocorram outras
construções de índices regulares na mesma tabela ao mesmo tempo,
mas só pode haver uma construção de índice concorrente em uma
tabela por vez.
Nos dois casos, nenhum outro tipo de modificação do esquema da
tabela é permitido enquanto o índice está sendo construído.
Outra diferença, é que um comando REINDEX TABLE
ou REINDEX INDEX regular pode ser
executado dentro de um bloco de transação, mas
REINDEX CONCURRENTLY não pode.
Como qualquer transação de longa duração, o comando
REINDEX de uma tabela pode afetar as tuplas
que podem ser removidas pelo comando VACUUM
simultâneo em qualquer outra tabela.
O comando REINDEX SYSTEM não oferece suporte à
cláusula CONCURRENTLY, já que os catálogos do
sistema não podem ser reindexados de forma concorrente.
Além disso, os índices para restrições de exclusão não podem ser
reindexados de forma concorrente.
Se tal índice for especificado diretamente neste comando,
será relatado erro.
Se uma tabela ou banco de dados com índices de restrição de exclusão
for reindexado de forma concorrente, estes índices serão ignorados.
(É possível reindexar estes índices sem a opção
CONCURRENTLY.)
Cada processo servidor executando REINDEX
relata seu progresso na visão
pg_stat_progress_create_index.
Veja Relatório de progresso do CREATE INDEX
para obter detalhes.
Reconstruir um único índice:
REINDEX INDEX my_index;
Reconstruir todos os índices na tabela my_table:
REINDEX TABLE my_table;
Reconstruir todos os índices em um banco de dados específico, sem confiar que os índices do sistema já estejam válidos:
$ export PGOPTIONS="-P" $ psql broken_db ... broken_db=> REINDEX DATABASE broken_db; broken_db=> \q
Reconstruir índices para uma tabela, sem bloquear as operações de leitura e escrita nas relações envolvidas enquanto a reindexação está em andamento:
REINDEX TABLE CONCURRENTLY my_broken_table;
Não existe o comando REINDEX no padrão
SQL.