Qual fator de preenchimento da tabela em cache?

10

Tenho uma tabela altamente atualizada / acessada onde armazeno objetos java serializados. Eles ficam na tabela por 2-3 horas (também estão sendo atualizados durante esse período) e depois são removidos. O tamanho da tabela é de cerca de 300 MB. Eu descobri que é muito, muito frequentemente aspirado e me pergunto se mudar o fillfactorajudaria?

Michal
fonte

Respostas:

17

As palavras-chave aqui são:

  1. "fortemente atualizado"
  2. "na mesa por 2-3 horas".

O ponto 1. é uma indicação para um fator de preenchimento mais baixo, enquanto 2. é o oposto. Ajuda o desempenho se várias versões de linha forem armazenadas na mesma página de dados. As atualizações HOT conseguiriam isso. Leia aqui ou aqui . Eles precisam de algum espaço de manobra na página de dados - como tuplas mortas ou espaço reservado por fillfactor<100. Mas eles só podem fazer o que precisam , se nenhum índice envolver qualquer uma das colunas atualizadas , o que deve ser verdadeiro para o seu caso.

Outro fator importante aqui seria o tamanho da tupla (em comparação com o tamanho da sua página (que geralmente é de 8 kb). Mais detalhes nesta resposta relacionada:

Se o tamanho da tupla for 4 kb ou mais, a redução do fator de preenchimento seria inútil, pois nunca poderá haver mais de uma tupla em uma página de dados. Você também pode deixá-lo em 100(que é o padrão de qualquer maneira). No entanto, alguns tipos de dados são "brindados" e armazenados fora de linha se excederem um limite de tamanho; portanto, as tuplas que exigem muito da relação principal são raras.

Faça o que fizer, VACUUM será executado com frequência. E isso geralmente é uma coisa boa, eu não me preocuparia com isso. Você cria muitas tuplas mortas. VACUUMidentifica linhas mortas que não são mais visíveis para nenhuma transação aberta. O manual:

O formato padrão VACUUMremove as versões de linha morta em tabelas e índices e marca o espaço disponível para reutilização futura .

Negrito ênfase minha.
Você pode jogar com configurações por tabela para o vácuo automático para acioná-lo com menos (ou mais) frequentemente apenas para esta tabela:

Os limites padrão e os fatores de escala são obtidos postgresql.conf, mas é possível substituí-los tabela por tabela ;

Negrito ênfase minha. Em particular com autovacuum_vacuum_thresholdeautovacuum_vacuum_scale_factor . Correr VACUUMmuito pode realmente ser uma boa ideia, em vez de muito baixa fillfacter. Isso depende dos padrões de acesso. Se todas as tuplas viverem, digamos, 3 horas e cada uma for atualizada várias vezes, eu ainda reduziria fillfactorpara algo como 50. Você terá que testar e encontrar o ponto ideal.

Alternativas

Tudo isso à parte, já que seus dados parecem voláteis, para começar: use uma UNLOGGEDtabela :

Os dados gravados em tabelas não registradas não são gravados no log write-ahead (consulte o Capítulo 29 ), o que os torna consideravelmente mais rápidos que as tabelas comuns. No entanto, eles não são à prova de falhas : uma tabela não registrada é truncada automaticamente após uma falha ou um desligamento não limpo. O conteúdo de uma tabela não registrada também não é replicado para servidores em espera.

Negrito ênfase minha. Não use isso se o servidor falhar e você ainda precisar dos dados posteriormente. Mas se estivermos falando sobre dados de sessão para aplicativos da web, esse pode ser um preço aceitável a ser pago.

Ou, ainda mais radical: use um armazenamento de valores-chave como o Redis, se você puder ficar sem os recursos e a segurança fornecidos por um RDBMS.

Erwin Brandstetter
fonte
Eu acho que não explorada é exatamente o que eu preciso
Michal
0

Eu sugeriria um DBMS de valor-chave, mas eu o jogo lá fora, por interesse.

Em vez de executar instruções INSERT & DELETE, faça apenas UPDATEs.

A estrutura da tabela será algo como

ID      integer  -- sequential ID
Used    boolean  -- default FALSE
Object  -- whatever type is appropriate

A coluna de retenção de objetos terá um comprimento fixo para evitar divisões e movimentos de linhas. Dimensione esta coluna para acomodar seus objetos e preencher com eficiência uma página no disco.

Pré-preencha sua tabela com quantas linhas forem necessárias e mais algumas.

Quando um objeto deve ser gravado, localize uma linha com Used = False e UPDATE nessa linha. Quando um objeto deve ser destruído, defina-o Usado como "Falso". Não há lixo criado e, portanto, não há coleta de lixo.

É claro que existem muitas, muitas condições de exceção a serem tratadas (estouro de linha, estouro de tabela, condições de corrida no uso de ID etc.), mas nenhuma é insuperável.

Michael Green
fonte
Pelo que entendi, essas ATUALIZAÇÕES normalmente ainda gravam uma cópia totalmente nova da linha no disco, a menos que seja uma atualização QUENTE. Então você ainda precisa de GC / aspiração ao longo do tempo.
22616 Jeff Jeffman