Otimizando o PostgreSQL para dados transitórios

8

Eu tenho várias tabelas com 100-300 colunas de tipos inteiros cada, que contêm dados altamente voláteis. Os conjuntos de dados são codificados por uma ou duas chaves primárias e, quando ocorre a atualização, o conjunto de dados inteiro é excluído e novos dados são inseridos em uma transação. O tamanho do conjunto de dados geralmente é de algumas centenas de linhas, mas pode atingir vários milhares de linhas em casos extremos. A atualização ocorre uma vez por segundo e as atualizações do conjunto de dados para chaves diferentes geralmente são desarticuladas, portanto, não é possível soltar e recriar a tabela.

Como ajusto o Postgres para lidar com essa carga? Posso usar a versão mais recente e melhor se isso fizer alguma diferença.

Alex Tokarev
fonte

Respostas:

7

Dependendo de quantos conjuntos de dados diferentes existem, uma opção seria particionar as tabelas por conjunto de dados.

Quando um conjunto de dados é atualizado, BEGINuma nova transação, TRUNCATEa tabela, COPYos novos dados nele e COMMIT. O PostgreSQL possui uma otimização na qual COPYuma tabela que foi TRUNCATEd na mesma transação faz muito menos E / S se você estiver usando wal_level = minimal(o padrão).

Se você não puder particionar e truncar (por exemplo, se estiver lidando com dezenas ou centenas de milhares de conjuntos de dados, onde haveria muitas tabelas), será melhor acionar o autovacuum para executar o máximo possível , verifique se você possui bons índices em tudo o que excluir com base e esteja preparado para um desempenho um tanto comum.

Se você não precisa de segurança contra falhas - você não se importa que suas tabelas estejam vazias após uma falha no sistema - você também pode criar suas tabelas como UNLOGGED, o que economizará uma enorme quantidade de custo de E / S.

Se você não se importa em restaurar toda a configuração de um backup após uma falha no sistema, pode ir além e também definir fsync=off, o que basicamente diz ao PostgreSQL "não se preocupe com a segurança de falhas, eu tenho bons backups e não não me importo se meus dados são permanentemente e totalmente irrecuperáveis ​​após uma falha e estou feliz em voltar initdbantes de poder usar meu banco de dados novamente ".

Escrevi um pouco mais sobre isso em um tópico semelhante no Stack Overflow sobre a otimização do PostgreSQL para testes rápidos ; que menciona o ajuste do SO do host, separando o WAL em um disco diferente, se você não estiver usando unloggedtabelas, ajustes no indicador de verificação, etc.

Há também algumas informações nos documentos da página para carregamento rápido de dados e configurações não duráveis .

Craig Ringer
fonte
Obrigado pela dica da partição, nunca pensei em usá-los nesse caso. Quanto às tabelas não registradas - você quer dizer que elas acabam vazias por padrão após a falha do sistema? Não faz diferença, só estou curioso.
Alex Tokarev
11
@AlexTokarev Isso mesmo; depois que o PostgreSQL é encerrado de maneira não limpa (postmaster ou um back-end segfaults, ciclos de energia do sistema repentinamente, back-end é SIGKILLeditado, etc.), qualquer UNLOGGEDtabela pode ser TRUNCATEd, então ela está vazia na inicialização. Eles não são truncados após um desligamento e uma reinicialização limpos, mas você não deve confiar neles como duráveis.
Craig Ringer
Obrigada pelo esclarecimento. Não preciso de segurança de dados para as tabelas em questão, os dados neles são transitórios e são atualizados da fonte a cada segundo. Desativar o fsync não é uma opção, pois existem outras tabelas mais tradicionais no mesmo esquema que precisam ser seguras e recuperáveis. Ter a UNLOGGEDopção por mesa é simplesmente ótimo.
Alex Tokarev
Estou analisando o documento de particionamento e parece que poderia ser uma solução (quase) perfeita para o problema. Porém, uma pergunta: se eu vou ter uma tabela pai para tabelas de esquema e filho para armazenar os dados, vou consultar os dados da tabela pai, certo? Se uma tabela filho para esse intervalo existir, a consulta retornará, caso contrário, retornará um conjunto de dados vazio. Nesse caso, posso até eliminar e recriar tabelas filho para cada lote de dados novo. Dadas as circunstâncias, o que será mais eficaz, TRUNCATEou DROP/CREATE TABLEsequência?
AlexKarevev
@AlexTokarev Eu recomendo que você TRUNCATE, pessoalmente. A rotatividade de DDL tem seus próprios custos. Como você faz alterações com tanta frequência, será muito importante garantir que você ative a agressividade do autovacuum pg_catalog.pg_classe outras tabelas do sistema que possam inchar com essa carga de trabalho.
Craig Ringer