Por que o desempenho da consulta PostGresql cai ao longo do tempo, mas restaurado quando a reconstrução Índice

StackOverflow https://stackoverflow.com/questions/2392982

Pergunta

De acordo com isso página no manual, indexes don't need to be maintained. No entanto, estamos executando com uma tabela PostgreSQL que possui uma taxa contínua de updates, deletes e inserts Com o tempo (alguns dias) vê uma degradação significativa da consulta. Se excluirmos e recriar o índice, o desempenho da consulta será restaurado.

Estamos usando as configurações da caixa.
A tabela em nosso teste está atualmente começando vazia e cresce para meio milhão de linhas. Possui uma linha bastante grande (muitos campos de texto).

Nós somos searching based of an index, not the primary key (Confirmei que o índice está sendo usado, pelo menos em condições normais)

A tabela está sendo usada como uma loja persistente para um único processo. Usando o PostGresql no Windows com um cliente Java.

Estou disposto a desistir insert and update performance Para manter o desempenho da consulta.

Estamos pensando em pesquisar o aplicativo para que os dados sejam espalhados por várias tabelas dinâmicas de uma maneira que nos permita cair e reconstruir índices periodicamente sem afetar o aplicativo. No entanto, como sempre, há uma crise de tempo para fazer isso funcionar e suspeito que estamos perdendo algo básico em nossa configuração ou uso.

Nós consideramos forcing vacuuming e rebuild to run at certain times, mas eu suspeito do locking period for such an action would cause our query to block. Isso pode ser uma opção, mas existem algumas implicações em tempo real (Windows de 3-5 segundos) que exigem outras alterações em nosso código.

Informação adicional:Tabela e índice

CREATE TABLE icl_contacts
(
  id bigint NOT NULL,
  campaignfqname character varying(255) NOT NULL,
  currentstate character(16) NOT NULL,
  xmlscheduledtime character(23) NOT NULL,
...
25 or so other fields.  Most of them fixed or varying character fiel  
...
  CONSTRAINT icl_contacts_pkey PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
ALTER TABLE icl_contacts OWNER TO postgres;

CREATE INDEX icl_contacts_idx
  ON icl_contacts
  USING btree
  (xmlscheduledtime, currentstate, campaignfqname);

Analisar:

Limit  (cost=0.00..3792.10 rows=750 width=32) (actual time=48.922..59.601 rows=750 loops=1)
  ->  Index Scan using icl_contacts_idx on icl_contacts  (cost=0.00..934580.47 rows=184841 width=32) (actual time=48.909..55.961 rows=750 loops=1)
        Index Cond: ((xmlscheduledtime < '2010-05-20T13:00:00.000'::bpchar) AND (currentstate = 'SCHEDULED'::bpchar) AND ((campaignfqname)::text = '.main.ee45692a-6113-43cb-9257-7b6bf65f0c3e'::text))

E sim, estou ciente de que há uma variedade de coisas we could do to normalize and improve the design of this table. Algumas dessas opções podem estar disponíveis para nós.

Meu foco nesta pergunta é sobre compreensão how PostgresQL is managing the index and query over time (understand why, not just fix). Se fosse feito sobre ou significativamente refatorado, haveria muitas mudanças.

Foi útil?

Solução

O vácuo automático deve fazer o truque, desde que você o configurou para o desempenho desejado.

Notas: A vácuo completo: Isso reconstruirá as estatísticas da tabela e recuperará cargas de espaço em disco. Ele trava a tabela inteira.

Vacuum: Isso reconstruirá as estatísticas da tabela e recuperará algum espaço em disco. Ele pode ser executado em paralelo com o sistema de produção, mas gera muito IO, o que pode afetar o desempenho.

Analisar: isso reconstruirá as estatísticas do planejador de consultas. Isso é desencadeado pelo vácuo, mas pode ser executado por conta própria.

Mais Notas detalhadas encontradas aqui

Outras dicas

Quanto ao desempenho, o uso de strings para armazenar tempo e informações sobre status é um gargalo. Primeiro de tudo, os índices nos textos são extremamente ineficientes, comparando duas vezes no mesmo dia, precisa de pelo menos 11 comparação (no formato que você usou), no entanto, usando o tipo de tempo que pode ser reduzido para simplesmente uma comparação. Isso também afeta o tamanho do índice e é difícil pesquisar um grande índice, e o banco de dados não o mantém na memória. As mesmas considerações se aplicam à coluna do estado. Se representar um pequeno conjunto de estados, você deve usar números inteiros mapeados para os estados, isso reduzirá os nós do índice - e o tamanho do índice de acordo. Além disso, esse índice será inútil, mesmo usando os tipos internos se você não especificar o tempo real da sua consulta.

Isso cheira a inchaço de índice para mim. Eu o encaminharei para esta página

http://www.postgresql.org/docs/8.3/static/routine-reindex.html

que diz na parte inferior:

Além disso, para o B-Tree Index, um índice recém-construído é um pouco mais rápido para acessar do que um que foi atualizado muitas vezes, porque as páginas logicamente adjacentes também são geralmente fisicamente adjacentes em um índice recém-construído. (Essa consideração não se aplica atualmente a índices não-B-Tree.) Pode valer a pena reindex periodicamente apenas para melhorar a velocidade de acesso.

O que parece entrar em conflito com a página que você referenciou dizendo que os índices "não exigem manutenção ou ajuste".

Você já tentou "criar índice simultaneamente"?

O valor '2010-05-20T13: 00: 00.000' é que o XMLSCHEDULEDTEM está sendo comparado a, parte do SQL ou fornecido como um parâmetro?

Ao planejar como executar a consulta, dizer que um campo deve ser menor que um parâmetro fornecido com um valor ainda desconhecido, não dá muito a continuar. Não sabe se isso corresponderá a quase todas as linhas, ou quase nenhuma das linhas.

Lendo sobre Como o planejador usa estatísticas Ajuda tremendamente ao tentar descobrir por que seu banco de dados está usando os planos.

Você pode obter melhor desempenho selecionado alterando a ordem dos campos nesse índice complexo ou criando um novo índice, com os campos ordenados (Campaignfname, CurrentState, XMLScheduledTime) desde então o índice levará você diretamente ao nome da campanha FQ e ao estado atual que você está interessado e a varredura de índice sobre o intervalo XMLScheduledtime serão todas linhas que você procura.

Esse é um caso de livro didático. Você deve configurar o Autovacuum para ser muito mais agressivo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top