O desempenho ideal do PostgreSQL depende da configuração correta dos parâmetros do sistema operacional. Parâmetros inadequados do núcleo do SO podem levar à redução do desempenho do servidor de banco de dados. Portanto, é essencial que esses parâmetros sejam ajustados de acordo com o servidor de banco de dados e sua carga de trabalho. Neste post, discutiremos alguns parâmetros importantes do núcleo do Linux que podem impactar o desempenho do servidor de banco de dados e como configurá-los.
SHMMAX / SHMALL
SHMMAX é um parâmetro do núcleo usado para determinar o tamanho máximo de um único segmento de memória compartilhada que um processo Linux pode alocar. Até a versão 9.2, o PostgreSQL usava System V (SysV), para o qual é necessário configurar o SHMMAX. Após 9.2, o PostgreSQL mudou para memória compartilhada POSIX. Portanto, agora é necessário menos bytes de memória compartilhada SysV.
Até a versão 9.3, o SHMMAX era o parâmetro mais importante do núcleo. O valor do SHMMAX é definido em bytes.
Da mesma forma, SHMALL é outro parâmetro do núcleo usado para determinar
o volume total de páginas de memória compartilhada do sistema. Para visualizar os valores atuais de SHMMAX, SHMALL ou SHMMIN, use o comando ipcs.
Detalhes de SHM* — Linux
$ ipcs -lm
------ Limites de Memória Compartilhada --------
max número de segmentos = 4096
max tamanho de segmento (kbytes) = 1073741824
max total de memória compartilhada (kbytes) = 17179869184
min tamanho de segmento (bytes) = 1Detalhes de SHM* — MacOS X
$ ipcs -M
Estado IPC a partir de as de Qui, 16 de Ago 22:20:35 PKT 2018
shminfo:
shmmax: 16777216 (tamanho máximo do segmento de memória compartilhada)
shmmin: 1 (tamanho mínimo do segmento de memória compartilhada)
shmmni: 32 (número máximo de identificadores de memória compartilhada)
shmseg: 8 (número máximo de segmentos de memória compartilhada por processo)
shmall: 1024 (quantidade máxima de memória compartilhada em páginas)
O PostgreSQL usa System V IPC para alocar memória compartilhada. Este parâmetro é um dos mais importantes do núcleo. Sempre que você recebe as seguintes mensagens de erro, isso significa que você tem uma versão mais antiga do PostgreSQL e um valor SHMMAX muito baixo. Espera-se que os usuários ajustem e aumentem o valor de acordo com a memória compartilhada que pretendem usar.
Possíveis erros de configuração incorreta
Se o SHMMAX estiver configurado incorretamente, você pode receber um erro ao tentar inicializar um cluster PostgreSQL usando o comando initdb.
Falha no initdb
DETALHE: A chamada de sistema falhou foi shmget(key=1, size=2072576, 03600).
DICA: Este erro geralmente significa que o pedido do PostgreSQL para um segmento de memória compartilhada excedeu o parâmetro SHMMAX do seu núcleo.
Você pode reduzir o tamanho da solicitação ou reconfigurar o núcleo com um SHMMAX maior. Para reduzir o tamanho da solicitação (atualmente 2072576 bytes),
reduza o uso de memória compartilhada do PostgreSQL, possivelmente reduzindo shared_buffers ou max_connections.
Se o tamanho da solicitação já for pequeno, pode ser que seja menor que o parâmetro SHMMIN do seu núcleo,
nesse caso, aumentar o tamanho da solicitação ou reconfigurar o SHMMIN é necessário.
A documentação do PostgreSQL contém mais informações sobre a configuração de memória compartilhada. O processo filho saiu com o código de saída 1.
Da mesma forma, você pode receber um erro ao iniciar o servidor PostgreSQL usando o comando pg_ctl.
Falha no pg_ctl
DETALHE: A chamada de sistema falhou foi shmget(key=5432001, size=14385152, 03600).
DICA: Este erro geralmente significa que o pedido do PostgreSQL para um segmento de memória compartilhada excedeu o parâmetro SHMMAX do seu núcleo.
Você pode reduzir o tamanho da solicitação ou reconfigurar o núcleo com um SHMMAX maior. Para reduzir o tamanho da solicitação (atualmente 14385152 bytes), reduza o uso de memória compartilhada do PostgreSQL, possivelmente reduzindo shared_buffers ou max_connections.
Se o tamanho da solicitação já for pequeno, pode ser que seja menor que o parâmetro SHMMIN do seu núcleo,
nesse caso, aumentar o tamanho da solicitação ou reconfigurar o SHMMIN é necessário.
A documentação do PostgreSQL contém mais informações sobre a configuração de memória compartilhada.
Compreendendo as diferenças nas definições
A definição dos parâmetros SHMMAX/SHMALL é ligeiramente diferente no Linux e no MacOS X:
- Linux: kernel.shmmax, kernel.shmall
- MacOS X: kern.sysv.shmmax, kern.sysv.shmall
Time sysctl pode ser usado para alterar temporariamente o valor. Para definir valores permanentes, adicione uma entrada em /etc/sysctl.conf. Mais detalhes estão abaixo.
Alteração dos parâmetros do núcleo no MacOS X
# Get the value of SHMMAX
sudo sysctl kern.sysv.shmmax
kern.sysv.shmmax: 4096
# Get the value of SHMALL
sudo sysctl kern.sysv.shmall
kern.sysv.shmall: 4096
# Set the value of SHMMAX
sudo sysctl -w kern.sysv.shmmax=16777216
kern.sysv.shmmax: 4096 -> 16777216
# Set the value of SHMALL
sudo sysctl -w kern.sysv.shmall=16777216
kern.sysv.shmall: 4096 -> 16777216Alteração dos parâmetros do núcleo no Linux
# Get the value of SHMMAX
sudo sysctl kernel.shmmax
kernel.shmmax: 4096
# Get the value of SHMALL
sudo sysctl kernel.shmall
kernel.shmall: 4096
# Set the value of SHMMAX
sudo sysctl -w kernel.shmmax=16777216
kernel.shmmax: 4096 -> 16777216
# Set the value of SHMALL
sudo sysctl -w kernel.shmall=16777216
kernel.shmall: 4096 -> 16777216Não se esqueça: para tornar as alterações permanentes, adicione esses valores em /etc/sysctl.conf
Páginas grandes (Huge Pages)
No Linux, por padrão, são usadas páginas de memória de 4 KB, no BSD — Super Pages, e no Windows — Large Pages. Uma página é uma parte da memória RAM alocada para um processo. Um processo pode ter várias páginas, dependendo das exigências de memória. Quanto mais memória um processo precisar, mais páginas lhe são alocadas. O sistema operacional mantém uma tabela de alocação de páginas para processos. Quanto menor o tamanho da página, maior a tabela, e mais tempo leva para procurar uma página nesta tabela de páginas. Portanto, páginas grandes permitem o uso de uma grande quantidade de memória com despesas gerais reduzidas; menos acessos às páginas, menos erros de página, operações de leitura/escrita mais rápidas através de buffers maiores. Como resultado, ocorre uma melhoria no desempenho.
O PostgreSQL suporta grandes páginas apenas no Linux. Por padrão, o Linux usa páginas de memória de 4 KB, então em casos onde há muitas operações com memória, é necessário definir páginas maiores. Observa-se um ganho de desempenho ao usar grandes páginas de 2 MB até 1 GB. O tamanho da grande página pode ser definido durante a inicialização. Você pode facilmente verificar os parâmetros das grandes páginas e seu uso no seu computador Linux usando o comando cat /proc/meminfo | grep -i huge.
Obtendo informações sobre grandes páginas (apenas no Linux)
Nota: Isso é apenas para Linux, para outros sistemas operacionais essa operação é ignorada$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kBNeste exemplo, embora o tamanho da grande página esteja definido como 2048 (2 MB), o número total de grandes páginas é 0. Isso significa que as grandes páginas estão desativadas.
Script para determinar o número de grandes páginas
Este é um script simples que retorna o número necessário de grandes páginas. Execute o script no seu servidor Linux enquanto o PostgreSQL estiver em execução. Certifique-se de que a variável de ambiente $PGDATA está definida para o diretório de dados do PostgreSQL.
Obtendo o número de grandes páginas necessárias
#!/bin/bash
pid=`head -1 $PGDATA/postmaster.pid`
echo "Pid: $pid"
peak=`grep ^VmPeak /proc/$pid/status | awk '{ print $2 }'`
echo "VmPeak: $peak kB"
hps=`grep ^Hugepagesize /proc/meminfo | awk '{ print $2 }'`
echo "Hugepagesize: $hps kB"
hp=$((peak/hps))
echo Set Huge Pages: $hpA saída do script é a seguinte:
Saída do script
Pid: 12737
VmPeak: 180932 kB
Hugepagesize: 2048 kB
Set Huge Pages: 88O valor recomendado para grandes páginas é 88, então você deve definir 88.
Definindo grandes páginas
sysctl -w vm.nr_hugepages=88Verifique as grandes páginas agora, você verá que as grandes páginas não estão sendo usadas (HugePages_Free = HugePages_Total).
Mais uma vez, informações sobre grandes páginas (apenas no Linux)
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 88
HugePages_Free: 88
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kBAgora defina o parâmetro huge_pages como "on" em $PGDATA/postgresql.conf e reinicie o servidor.
E novamente, informações sobre grandes páginas (apenas no Linux)
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 88
HugePages_Free: 81
HugePages_Rsvd: 64
HugePages_Surp: 0
Hugepagesize: 2048 kBAgora você pode ver que muito poucas grandes páginas estão sendo usadas. Vamos tentar adicionar alguns dados ao banco de dados.
Algumas operações com o banco de dados para a utilização de grandes páginas
postgres=# CREATE TABLE foo(a INTEGER);
CREATE TABLE
postgres=# INSERT INTO foo VALUES(generate_Series(1,10000000));
INSERT 0 10000000Vamos ver se estamos usando mais grandes páginas do que antes.
Mais uma vez, informações sobre grandes páginas (apenas no Linux)
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 88
HugePages_Free: 18
HugePages_Rsvd: 1
HugePages_Surp: 0
Hugepagesize: 2048 kBAgora você pode ver que a maioria das grandes páginas está sendo usada.
Nota: o valor aproximado para HugePages usado aqui é muito baixo, o que não é um valor normal para uma máquina em ambiente de produção. Por favor, avalie a quantidade necessária de páginas para o seu sistema e configure-as de acordo com a carga e os recursos.
vm.swappiness
vm.swappiness — este é mais um parâmetro do kernel que pode influenciar o desempenho do banco de dados. Esse parâmetro é usado para gerenciar o comportamento da troca (swappiness) (paginação de páginas para dentro e para fora da memória) no Linux. O valor varia de 0 a 100. Ele determina quanto da memória será descartado ou liberado. Zero significa que a troca está desativada, enquanto 100 significa uma troca agressiva.
Você pode obter um bom desempenho configurando valores mais baixos.
Definir o valor 0 em kernels mais novos pode fazer com que o OOM Killer (processo de limpeza de memória no Linux) mate o processo. Assim, pode-se definir com segurança o valor 1, se desejar minimizar a troca. O valor padrão no Linux é 60. Um valor mais alto faz com que o MMU (unidade de gerenciamento de memória) use mais espaço de troca do que a RAM, enquanto um valor mais baixo mantém mais dados/código na memória.
Um valor menor é uma boa aposta para melhorar o desempenho no PostgreSQL.
vm.overcommit_memory / vm.overcommit_ratio
Aplicativos obtêm memória e a liberam quando não precisam mais dela. Mas em alguns casos, um aplicativo obtém memória demais e não a libera. Isso pode provocar o OOM killer. Aqui estão os possíveis valores do parâmetro vm.overcommit_memory com uma descrição para cada um:
- Overcommit heurístico (padrão); heurística baseada no kernel
- Permitir overcommit em qualquer caso
- Não exagere, não ultrapasse a taxa de overcommit.
Link:
vm.overcommit_ratio — porcentagem da memória RAM disponível para sobrecarga excessiva. Um valor de 50% em um sistema com 2 GB de RAM pode alocar até 3 GB de RAM.
Um valor de 2 para vm.overcommit_memory oferece melhor desempenho para PostgreSQL. Esse valor maximiza o uso da memória RAM pelo processo do servidor sem risco significativo de ser encerrado pelo processo OOM killer. O aplicativo poderá reiniciar, mas apenas dentro do limite do excedente, reduzindo o risco de o OOM killer encerrar o processo. Portanto, um valor de 2 proporciona melhor desempenho do que o valor padrão de 0. No entanto, a confiabilidade pode ser melhorada, pois a memória além do limite permitido não será sobrecarregada. Isso elimina o risco de o processo ser encerrado pelo OOM killer.
Em sistemas sem swap, pode ocorrer um problema com vm.overcommit_memory igual a 2.
vm.dirty_background_ratio / vm.dirty_background_bytes
vm.dirty_background_ratio — é a porcentagem de memória preenchida com páginas sujas que precisam ser gravadas no disco. A gravação no disco é feita em segundo plano. O valor desse parâmetro varia de 0 a 100; no entanto, um valor abaixo de 5 pode ser ineficaz, e alguns kernels não o suportam. 10 é o valor padrão na maioria dos sistemas Linux. Você pode aumentar o desempenho para operações de gravação intensiva com uma proporção menor, o que significa que o Linux gravará páginas sujas em segundo plano.
Você precisa definir o valor vm.dirty_background_bytes de acordo com a velocidade do seu disco.
Para esses dois parâmetros, não há 'bons' valores, pois ambos dependem do hardware. No entanto, definir vm.dirty_background_ratio para 5 e vm.dirty_background_bytes para 25% da velocidade do disco melhora o desempenho em cerca de 25% na maioria dos casos.
vm.dirty_ratio / dirty_bytes
Isso é o mesmo que vm.dirty_background_ratio / dirty_background_bytes, exceto que a gravação é feita durante a sessão ativa, bloqueando o aplicativo. Portanto, vm.dirty_ratio deve ser superior a vm.dirty_background_ratio. Isso garante que os processos em segundo plano sejam iniciados mais cedo para evitar o bloqueio máximo do aplicativo. Você pode ajustar a diferença entre essas duas razões com base na carga de E/S do disco.
Resultado
Você pode ajustar outras configurações para aumentar o desempenho, mas as melhorias serão mínimas e os benefícios não serão significativos. Devemos lembrar que nem todas as configurações se aplicam a todos os tipos de aplicativos. Alguns aplicativos funcionam melhor quando ajustamos certas configurações, enquanto outros não. Você deve encontrar um equilíbrio adequado entre as configurações dessas opções para a carga de trabalho esperada e o tipo de aplicativo, além de levar em conta o comportamento do sistema operacional ao configurá-las. Ajustar as configurações do kernel não é tão simples quanto ajustar as configurações do banco de dados: aqui é mais complicado fornecer recomendações.
Fonte: habr.com
