Optimizar el uso elevado de CPU en las instancias

Un uso elevado de la CPU afecta negativamente al rendimiento de la instancia. Cualquier actividad que se realice en la instancia usa CPU. Por lo tanto, si recibes una notificación de uso elevado de la CPU, primero debes identificar la causa principal del problema, ya sean consultas mal escritas, transacciones de larga duración o cualquier otra actividad de la base de datos.

En este documento se describen las formas de identificar los cuellos de botella de la CPU en una instancia y de mitigar los problemas de utilización de la CPU en la instancia.

Identificar los cuellos de botella de la CPU

En las siguientes secciones se describen diferentes situaciones de CPU.

Usar Información útil sobre las consultas para identificar las consultas que tienen un consumo de CPU elevado

Información valiosa sobre las consultas te ayuda a detectar, diagnosticar y evitar problemas de rendimiento de las consultas en las bases de datos de Cloud SQL.

Usar la extensión pg_proctab

Usa la extensión pg_proctab con la utilidad pg_top para obtener resultados del sistema operativo que proporcionen información sobre el uso de la CPU por proceso.

Usar consultas

En las siguientes secciones se describen las diferentes consultas que puedes usar.

Identificar las conexiones activas por estado

Cada conexión activa a la base de datos ocupa una cantidad de CPU, por lo que, si la instancia tiene un gran número de conexiones, la utilización acumulativa podría ser alta. Usa la siguiente consulta para obtener información sobre el número de conexiones por estado.

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

El resultado es similar al siguiente:


        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)

Si el número de conexiones activas es alto, comprueba si hay consultas de larga duración o eventos de espera que impidan que se ejecuten las consultas.

Si el número de conexiones inactivas es alto, ejecuta la siguiente consulta para finalizar las conexiones después de obtener las aprobaciones necesarias.

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

También puedes finalizar las conexiones de forma individual con pg_terminate_backend mediante la siguiente consulta:

SELECT pg_terminate_backend (<pid>);

Aquí puedes obtener el PID de pg_stat_activity.

Identificar las conexiones de larga duración

A continuación se muestra un ejemplo de una consulta que devuelve consultas de larga duración. En este caso, puede identificar las consultas que han estado activas durante más 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;

Revisar el plan de explicación para identificar consultas mal escritas

Usa EXPLAIN PLAN para investigar una consulta mal escrita y reescribirla si es necesario. También puedes cancelar la consulta de larga duración con el siguiente comando y las aprobaciones necesarias.

SELECT pg_cancel_backend(<pid>);

Monitorizar la actividad de VACUUM

La actividad AUTOVACUUM que elimina las tuplas inactivas es una operación que requiere muchos recursos de CPU. Si tu instancia usa PostgreSQL versión 11 o posterior, usa la siguiente consulta para comprobar si hay alguna actividad AUTOVACUUM o VACUUM activa en 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;

Comprueba si hay una actividad VACUUM en curso en una instancia mediante la siguiente consulta:

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

Además, puedes optimizar y solucionar problemas de operaciones VACUUM en PostgreSQL.

Añadir la extensión pg_stat_statements

Configura la extensión pg_stat_statements para obtener información de diccionario mejorada sobre la actividad de la instancia.

Puntos de control frecuentes

Los puntos de control frecuentes degradan el rendimiento. Si el registro de alertas de PostgreSQL informa de la advertencia checkpoint occurring too frequently, considera la posibilidad de ajustar la marca checkpoint_timeout.

Recoger estadísticas

Asegúrate de que el planificador de consultas tenga las estadísticas más recientes sobre las tablas para elegir el mejor plan para las consultas. La operación ANALYZE recoge estadísticas sobre el contenido de las tablas de la base de datos y almacena los resultados en el catálogo del sistema pg_statistic. Después, el planificador de consultas usa estas estadísticas para ayudar a determinar los planes de ejecución más eficientes para las consultas. El proceso AUTOVACUUM analiza automáticamente las tablas periódicamente, así que ejecuta el siguiente comando para comprobar si se han analizado todas las tablas y si el planificador tiene disponibles los metadatos más recientes.

SELECT
  relname,
  last_autovacuum,
  last_autoanalyze
FROM
  pg_stat_user_tables;

Ajustes del sistema inadecuados

Hay otros factores y ajustes de marcas o factores del sistema que influyen en el rendimiento de tu consulta. Ejecuta la siguiente consulta para comprobar los eventos de espera y el tipo de evento de espera para obtener información valiosa sobre el rendimiento de otros ajustes del 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;

El resultado debe ser similar a este:


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

Monitorizar análisis secuenciales

Los análisis secuenciales frecuentes en tablas de más de unas decenas de filas suelen indicar que falta un índice. Cuando las lecturas tocan miles o incluso cientos de miles de filas, pueden provocar un uso excesivo de la CPU.

Los análisis secuenciales frecuentes en tablas con cientos de miles de filas pueden provocar un uso excesivo de la CPU. Para evitar las lecturas secuenciales en estas tablas, crea los índices necesarios.

Ejecuta la siguiente consulta para comprobar el número de veces que se inician análisis secuenciales en cualquier tabla.

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, si la CPU sigue estando alta y crees que esas consultas son tráfico legítimo, considera la posibilidad de aumentar los recursos de CPU de tu instancia para evitar que la base de datos falle o que se produzca un tiempo de inactividad.

Siguientes pasos