Otimize a utilização elevada da CPU em instâncias

A utilização elevada da CPU afeta negativamente o desempenho da sua instância. Qualquer atividade realizada na instância usa a CPU. Assim, se receber um aviso de utilização elevada da CPU, deve primeiro identificar a causa principal do problema, quer se trate de consultas mal escritas, transações de longa duração ou qualquer outra atividade da base de dados.

Este documento descreve as formas de identificar gargalos da CPU numa instância e mitigar os problemas de utilização da CPU na instância.

Identifique os gargalos da CPU

As secções seguintes abordam diferentes cenários de CPU.

Use as estatísticas de consultas para identificar consultas com um elevado consumo da CPU

As estatísticas de consultas ajudam a detetar, diagnosticar e evitar problemas de desempenho de consultas para bases de dados do Cloud SQL.

Use a extensão pg_proctab

Use a extensão pg_proctab com a combinação do utilitário pg_top para obter resultados do sistema operativo que fornecem informações de utilização da CPU por processo.

Use consultas

As secções seguintes abordam diferentes consultas que pode usar.

Identifique as ligações ativas por estado

Cada ligação ativa à base de dados ocupa uma determinada quantidade de CPU. Por isso, se a instância tiver um número elevado de ligações, a utilização cumulativa pode ser elevada. Use a seguinte consulta para obter as informações sobre o número de associações por estado.

SELECT
  state,
  usename,
  count(1)
FROM
  pg_stat_activity
WHERE
  pid <> pg_backend_pid()
group by
  state,
  usename
order by
  1;

O resultado tem um aspeto semelhante ao seguinte:


        state        |    usename    | count
---------------------+---------------+-------
 active              | ltest         |   318
 active              | sbtest        |    95
 active              |               |     2
 idle                | cloudsqladmin |     2
 idle in transaction | ltest         |    32
 idle in transaction | sbtest        |     5
                     | cloudsqladmin |     3
                     |               |     4
(8 rows)

Se a contagem de ligações ativas for elevada, verifique se existem consultas de execução prolongada ou eventos de espera que estão a impedir a execução das consultas.

Se a contagem de ligações inativas for elevada, execute a seguinte consulta para terminar as ligações, depois de receber as aprovações necessárias.

SELECT
  pg_terminate_backend(pid)
FROM
  pg_stat_activity
WHERE
  usename = 'sbtest'
  and pid <> pg_backend_pid()
  and state in ('idle');

Também pode terminar as associações individualmente com pg_terminate_backend através da seguinte consulta:

SELECT pg_terminate_backend (<pid>);

Aqui, pode obter o PID a partir do pg_stat_activity.

Identifique as associações de longa duração

Segue-se um exemplo de uma consulta que devolve consultas de execução prolongada. Neste caso, pode identificar as consultas que estão ativas há mais de 5 minutos.

SELECT
  pid,
  query_start,
  xact_start,
  now() - pg_stat_activity.query_start AS duration,
  query,
  state
FROM
  pg_stat_activity
WHERE
  (
    now() - pg_stat_activity.query_start
  ) > interval '5 minutes' order by 4 desc;

Reveja o plano de explicação para identificar consultas mal escritas

Use o EXPLAIN PLAN para investigar uma consulta mal escrita e reescrever a consulta, se necessário. Opcionalmente, considere cancelar a consulta de execução prolongada com o seguinte comando com as aprovações necessárias.

SELECT pg_cancel_backend(<pid>);

Monitorize a atividade de VACUUM

A atividade AUTOVACUUM que limpa as tuplas mortas é uma operação com elevado consumo da CPU. Se a sua instância usar a versão 11 ou posterior do PostgreSQL, use a seguinte consulta para verificar se existe alguma atividade AUTOVACUUM ou VACUUM ativa em curso.

SELECT
  relid :: regclass,
  pid,
  phase,
  heap_blks_total,
  heap_blks_scanned,
  heap_blks_vacuumed,
  index_vacuum_count,
  max_dead_tuples,
  num_dead_tuples
FROM
  pg_stat_progress_vacuum;

Verifique se existe uma atividade VACUUM em curso numa instância através da seguinte consulta:

SELECT
  pid,
  datname,
  usename,
  query
FROM
  pg_stat_activity
WHERE
  query like '%vacuum%';

Além disso, pode otimizar e resolver problemas relacionados com operações VACUUM no PostgreSQL.

Adicione a extensão pg_stat_statements

Configure a extensão pg_stat_statements para obter informações melhoradas do dicionário sobre a atividade da instância.

Postos de controlo frequentes

Os pontos de verificação frequentes degradam o desempenho. Considere ajustar a flag checkpoint_timeout se o registo de alertas do PostgreSQL comunicar o aviso checkpoint occurring too frequently.

Recolha estatísticas

Certifique-se de que o planeador de consultas tem as estatísticas mais recentes sobre as tabelas para escolher o melhor plano para as consultas. A operação ANALYZE recolhe estatísticas sobre o conteúdo das tabelas na base de dados e armazena os resultados no catálogo do sistema pg_statistic. Posteriormente, o planeador de consultas usa estas estatísticas para ajudar a determinar os planos de execução mais eficientes para as consultas. O processo AUTOVACUUM analisa automaticamente as tabelas periodicamente. Por isso, execute o seguinte comando para verificar se todas as tabelas foram analisadas e se têm os metadados mais recentes disponíveis para o planeador.

SELECT
  relname,
  last_autovacuum,
  last_autoanalyze
FROM
  pg_stat_user_tables;

Definições do sistema inadequadas

Existem outros fatores e definições de flags ou fatores do sistema que influenciam o desempenho da sua consulta. Execute a seguinte consulta para verificar os eventos de espera e o tipo de evento de espera para obter estatísticas sobre o desempenho de outras definições do sistema.

SELECT
  datname,
  usename,
  (
    case when usename is not null then state else query end
  ) AS what,
  wait_event_type,
  wait_event,
  backend_type,
  count(*)
FROM
  pg_stat_activity
GROUP BY
  1,
  2,
  3,
  4,
  5,
  6
ORDER BY
  1,
  2,
  3,
  4 nulls first,
  5,
  6;

O resultado tem o seguinte aspeto:


 ..  | .. | what           | wait_event_type |      wait_event      | ..    | count
-..--+-..-+----------------+-----------------+----------------------+-..----+------
 ..
 ..  | .. | active         | IO              | CommitWaitFlush      | ..    |   750
 ..  | .. | idle           | IO              | CommitWaitFlush      | ..    |   360
 ..  | .. | active         | LWLock          | BufferMapping        | ..    |   191

Monitorize análises sequenciais

As análises sequenciais frequentes em tabelas com mais de algumas dezenas de linhas indicam normalmente a falta de um índice. Quando as análises tocam em milhares ou até centenas de milhares de linhas, podem causar uma utilização excessiva da CPU.

As análises sequenciais frequentes em tabelas com centenas de milhares de linhas podem causar uma utilização excessiva da CPU. Evite as verificações sequenciais em tabelas deste tipo criando os índices necessários.

Execute a seguinte consulta para verificar o número de vezes que as análises sequenciais são iniciadas em qualquer tabela.

SELECT
  relname,
  idx_scan,
  seq_scan,
  n_live_tup
FROM
  pg_stat_user_tables
WHERE
  seq_scan > 0
ORDER BY
  n_live_tup desc;

Por último, se a utilização da CPU continuar elevada e considerar que essas consultas são tráfego legítimo, pondere aumentar os recursos da CPU na sua instância para evitar falhas ou indisponibilidade da base de dados.

O que se segue?