Estou mudando para o PostgreSQL do SQLite para uma aplicação típica do Rails.
O problema é que a execução de especificações ficou lenta com o PG.
No SQLite, demorou ~ 34 segundos, no PG, é ~ 76 segundos, o que é mais do que 2x mais lento .
Então agora eu quero aplicar algumas técnicas para melhorar o desempenho das especificações com o SQLite sem modificações de código (idealmente, basta definir as opções de conexão, o que provavelmente não é possível).
Algumas coisas óbvias do alto da minha cabeça são:
- Disco de RAM (seria bom ver uma boa configuração com o RSpec no OSX)
- Tabelas não registradas (elas podem ser aplicadas em todo o banco de dados para que eu não tenha que alterar todos os scripts?)
Como você deve ter entendido, não me importo com a confiabilidade e o resto (o banco de dados é apenas uma coisa descartável aqui).
Preciso tirar o máximo proveito do PG e torná-lo o mais rápido possível .
A melhor resposta descreveria idealmente os truques para fazer exatamente isso, a configuração e as desvantagens desses truques.
UPDATE: fsync = off
+ full_page_writes = off
diminuiu o tempo para ~ 65 segundos (~ -16 segundos). Bom começo, mas longe do objetivo de 34.
UPDATE 2: Eu tentei disco uso RAM , mas o ganho de desempenho estava dentro de uma margem de erro. Portanto, não parece valer a pena.
ATUALIZAÇÃO 3: * Encontrei o maior gargalo e agora minhas especificações são mais rápidas que as do SQLite.
O problema foi a limpeza do banco de dados que fez o truncamento . Aparentemente, o SQLite é muito rápido lá.
Para "corrigi-lo", abro uma transação antes de cada teste e a reverto no final.
Alguns números para ~ 700 testes.
- Truncamento: SQLite - 34s, PG - 76s.
- Transação: SQLite - 17s, PG - 18s.
Aumento de velocidade de 2x para SQLite. Aumento de velocidade de 4x para PG.
fonte
Respostas:
Primeiro, sempre use a versão mais recente do PostgreSQL. As melhorias de desempenho estão sempre chegando; portanto, você provavelmente está perdendo tempo se estiver ajustando uma versão antiga. Por exemplo, o PostgreSQL 9.2 melhora significativamente a velocidade
TRUNCATE
e, naturalmente, adiciona varreduras somente de índice. Mesmo versões menores sempre devem ser seguidas; consulte a política de versão .Não é
Você não colocar um espaço de tabela em um disco RAM ou outro armazenamento não-duráveis .
Se você perder um espaço de tabela, todo o banco de dados poderá ser danificado e difícil de usar sem um trabalho significativo. Há muito pouca vantagem nisso se comparado ao uso de
UNLOGGED
tabelas e à disponibilidade de muita RAM para cache.Se você realmente deseja um sistema baseado em ramdisk,
initdb
um cluster totalmente novo no ramdisk,initdb
inserindo uma nova instância do PostgreSQL no ramdisk, para ter uma instância do PostgreSQL completamente descartável.Configuração do servidor PostgreSQL
Ao testar, você pode configurar seu servidor para uma operação não durável, mas mais rápida .
Este é um dos únicos usos aceitáveis para a
fsync=off
configuração no PostgreSQL. Essa configuração praticamente diz ao PostgreSQL para não se preocupar com gravações ordenadas ou qualquer outra coisa desagradável de proteção à integridade de dados e segurança contra falhas, dando permissão para descartar totalmente seus dados se você perder energia ou ocorrer uma falha no sistema operacional.Desnecessário dizer que você nunca deve ativar a
fsync=off
produção, a menos que esteja usando a Pg como um banco de dados temporário para dados que você pode gerar novamente de outro lugar. Se e somente se você estiver fazendo para desativar o fsync, também é possívelfull_page_writes
desativar, pois não serve mais para nada. Cuidadofsync=off
efull_page_writes
aplique no nível do cluster , para que eles afetem todos os bancos de dados na sua instância do PostgreSQL.Para uso em produção, é possível usar
synchronous_commit=off
e definir umcommit_delay
, pois você terá muitos dos mesmos benefícios quefsync=off
sem o risco gigante de corrupção de dados. Você tem uma pequena janela de perda de dados recentes se ativar a confirmação assíncrona - mas é isso.Se você tiver a opção de alterar levemente o DDL, também poderá usar as
UNLOGGED
tabelas na página 9.1+ para evitar completamente o log do WAL e obter um aumento real da velocidade com o custo de as tabelas serem apagadas se o servidor travar. Não há opção de configuração para tornar todas as tabelas desmarcadas; ela deve ser definida duranteCREATE TABLE
. Além de ser bom para testar, isso é útil se você tiver tabelas cheias de dados gerados ou sem importância em um banco de dados que, de outra forma, contém coisas que você precisa estar seguro.Verifique seus logs e veja se você está recebendo avisos sobre muitos pontos de verificação. Se você é, você deve aumentar seus pontos de verificação . Você também pode ajustar seu checkpoint_completion_target para facilitar as gravações.
Ajuste
shared_buffers
para ajustar sua carga de trabalho. Isso depende do sistema operacional, depende do que mais está acontecendo com sua máquina e requer algumas tentativas e erros. Os padrões são extremamente conservadores. Pode ser necessário aumentar o limite máximo de memória compartilhada do sistema operacional se você aumentarshared_buffers
no PostgreSQL 9.2 e abaixo; 9.3 e acima mudaram a maneira como eles usam a memória compartilhada para evitar isso.Se você estiver usando apenas algumas conexões que dão muito trabalho, aumente
work_mem
para fornecer mais memória RAM para brincar, etc. Lembre-se de que umawork_mem
configuração muito alta pode causar problemas de falta de memória porque ela não é classificada por categoria. por conexão para que uma consulta possa ter várias classificações aninhadas. Você realmente precisa aumentarwork_mem
se conseguir ver as classificações sendo derramadas no discoEXPLAIN
ou logadas com alog_temp_files
configuração (recomendável), mas um valor mais alto também pode permitir que a Pg escolha planos mais inteligentes.Como dito por outro pôster aqui, é aconselhável colocar o xlog e as tabelas / índices principais em HDDs separados, se possível. Partições separadas são inúteis, você realmente deseja unidades separadas. Essa separação tem muito menos benefícios se você estiver executando com
fsync=off
e quase nenhum se estiver usandoUNLOGGED
tabelas.Por fim, ajuste suas consultas. Verifique
random_page_cost
eseq_page_cost
reflita o desempenho do seu sistema, verifique seeffective_cache_size
está correto, etc. UseEXPLAIN (BUFFERS, ANALYZE)
para examinar planos de consulta individuais e ligue oauto_explain
módulo para relatar todas as consultas lentas. Muitas vezes, é possível melhorar drasticamente o desempenho da consulta criando um índice apropriado ou aprimorando os parâmetros de custo.AFAIK não há como definir um banco de dados ou cluster inteiro como
UNLOGGED
. Seria interessante poder fazer isso. Considere perguntar na lista de discussão do PostgreSQL.Ajuste do SO do host
Também é possível fazer alguns ajustes no nível do sistema operacional. A principal coisa que você pode querer fazer é convencer o sistema operacional a não liberar gravações no disco de forma agressiva, pois você realmente não se importa quando / se elas o fazem no disco.
No Linux, você pode controlar isso com o subsistema de memória virtual 's
dirty_*
configurações, comodirty_writeback_centisecs
.O único problema com o ajuste das configurações de write-back é muito frouxo é que uma descarga por outro programa pode causar a descarga de todos os buffers acumulados do PostgreSQL também, causando grandes paradas enquanto tudo bloqueia as gravações. Você pode aliviar isso executando o PostgreSQL em um sistema de arquivos diferente, mas algumas descargas podem ser no nível do dispositivo ou no host inteiro e não no sistema de arquivos, portanto você não pode confiar nisso.
Esse ajuste realmente exige que você faça as configurações para ver o que funciona melhor para sua carga de trabalho.
Nos kernels mais recentes, convém garantir que
vm.zone_reclaim_mode
seja definido como zero, pois isso pode causar problemas graves de desempenho nos sistemas NUMA (na maioria dos sistemas atualmente) devido a interações com o gerenciamento do PostgreSQLshared_buffers
.Ajuste de consulta e carga de trabalho
São coisas que exigem alterações de código; eles podem não combina com você. Algumas são coisas que você pode aplicar.
Se você não estiver trabalhando em lotes em transações maiores, inicie. Muitas transações pequenas são caras, portanto, você deve agrupar as coisas sempre que possível e prático. Se você estiver usando a confirmação assíncrona, isso é menos importante, mas ainda é altamente recomendado.
Sempre que possível, use tabelas temporárias. Eles não geram tráfego WAL, portanto, são muito mais rápidos para inserções e atualizações. Às vezes, vale a pena incluir um monte de dados em uma tabela temporária, manipulá-los da maneira que você precisar e, em seguida, fazer uma
INSERT INTO ... SELECT ...
cópia para a tabela final. Observe que as tabelas temporárias são por sessão; se a sua sessão terminar ou você perder a conexão, a tabela temporária desaparecerá e nenhuma outra conexão poderá ver o conteúdo das tabelas temporárias de uma sessão.Se você estiver usando o PostgreSQL 9.1 ou mais recente, poderá usar
UNLOGGED
tabelas para dados que pode perder, como o estado da sessão. Eles são visíveis em diferentes sessões e preservados entre as conexões. Eles são truncados se o servidor for desligado de maneira não limpa, para que não possam ser usados para qualquer coisa que você não possa recriar, mas são ótimos para caches, visualizações materializadas, tabelas de estado etc.Em geral, não
DELETE FROM blah;
. Use emTRUNCATE TABLE blah;
vez disso; é muito mais rápido quando você descarta todas as linhas em uma tabela. Trunque muitas tabelas em umaTRUNCATE
chamada, se puder. Há uma ressalva se você estiver fazendo muitasTRUNCATES
mesas pequenas repetidamente; veja: Velocidade de truncamento do PostgresqlSe você não tiver índices em chaves estrangeiras, os
DELETE
s que envolvem as chaves primárias referenciadas por essas chaves estrangeiras serão terrivelmente lentos. Crie esses índices, se você esperaDELETE
da tabela (s) referenciada (s). Os índices não são necessários paraTRUNCATE
.Não crie índices desnecessários. Cada índice tem um custo de manutenção. Tente usar um conjunto mínimo de índices e permita que as varreduras de índice de bitmap as combinem, em vez de manter muitos índices enormes e caros de várias colunas. Onde os índices são necessários, tente preencher a tabela primeiro e depois crie índices no final.
Hardware
Ter RAM suficiente para armazenar todo o banco de dados é uma grande vitória, se você puder gerenciá-lo.
Se você não tiver RAM suficiente, quanto mais rápido o armazenamento, melhor. Mesmo um SSD barato faz uma enorme diferença em relação à ferrugem. Porém, não confie em SSDs baratos para produção, eles geralmente não são seguros contra falhas e podem consumir seus dados.
Aprendendo
O livro de Greg Smith, PostgreSQL 9.0 High Performance, continua relevante, apesar de se referir a uma versão um pouco mais antiga. Deve ser uma referência útil.
Entre na lista de discussão geral do PostgreSQL e siga-a.
Lendo:
fonte
Use um layout de disco diferente:
ajustes do postgresql.conf:
fonte
fsync=off
, colocar o pg_xlog em um disco separado não melhora muito.