sql >> Base de Datos >  >> RDS >> PostgreSQL

¿PostgreSQL va lento? Consejos y trucos para llegar a la fuente

Como administrador de la base de datos de PostgreSQL, existen las expectativas diarias de verificar las copias de seguridad, aplicar cambios DDL, asegurarse de que los registros no tengan ningún ERROR que rompa el juego y responder a las llamadas de pánico de los desarrolladores cuyos informes se ejecutan el doble de lo normal y tener una reunión en diez minutos.

Incluso con una buena comprensión de la salud de las bases de datos administradas, siempre habrá nuevos casos y nuevos problemas relacionados con el rendimiento y cómo se “siente” la base de datos. Ya sea que se trate de un correo electrónico de pánico o de un ticket abierto por "la base de datos se siente lenta", esta tarea común generalmente se puede seguir con algunos pasos para verificar si hay o no un problema con PostgreSQL, y cuál puede ser ese problema.

Esta no es una guía exhaustiva, ni es necesario realizar los pasos en un orden específico. Pero es más bien un conjunto de pasos iniciales que se pueden tomar para ayudar a encontrar rápidamente a los delincuentes comunes, así como obtener una nueva perspectiva de cuál puede ser el problema. Un desarrollador puede saber cómo actúa y responde la aplicación, pero el administrador de la base de datos sabe cómo actúa y responde la base de datos a la aplicación y, juntos, se puede encontrar el problema.

NOTA: Las consultas que se ejecutarán deben realizarse como un superusuario, como 'postgres' o cualquier usuario de la base de datos que tenga permisos de superusuario. Los usuarios limitados serán denegados o se omitirán los datos.

Paso 0 - Recopilación de información

Obtenga la mayor cantidad de información posible de quien diga que la base de datos parece lenta; consultas específicas, aplicaciones conectadas, marcos de tiempo de la lentitud del rendimiento, etc. Cuanta más información proporcionen, más fácil será encontrar el problema.

Paso 1 - Comprobar pg_stat_actividad

La solicitud puede venir en muchas formas diferentes, pero si la "lentitud" es el problema general, verificar pg_stat_activity es el primer paso para comprender qué está sucediendo. La vista pg_stat_activity (la documentación de cada columna de esta vista se puede encontrar aquí) contiene una fila para cada proceso del servidor/conexión a la base de datos desde un cliente. Hay un puñado de información útil en esta vista que puede ayudar.

NOTA: Se sabe que pg_stat_activity cambia de estructura con el tiempo, refinando los datos que presenta. La comprensión de las columnas en sí ayudará a crear consultas dinámicamente según sea necesario en el futuro.

Las columnas notables en pg_stat_activity son:

  1. consulta:una columna de texto que muestra la consulta que se está ejecutando actualmente, en espera de ser ejecutada o que se ejecutó por última vez (según el estado). Esto puede ayudar a identificar qué consulta/consultas puede estar informando un desarrollador que se están ejecutando lentamente.
  2. client_addr:la dirección IP desde la que se originó esta conexión y consulta. Si está vacío (o nulo), se originó en localhost.
  3. backend_start, xact_start, query_start:estos tres proporcionan una marca de tiempo de cuándo se inició cada uno, respectivamente. Backend_start representa cuándo se estableció la conexión a la base de datos, xact_start es cuando comenzó la transacción actual y query_start es cuando comenzó la consulta actual (o la última).
  4. estado:El estado de la conexión a la base de datos. Activo significa que actualmente está ejecutando una consulta, 'inactivo' significa que está esperando más información del cliente, 'inactivo en transacción' significa que está esperando más información del cliente mientras mantiene una transacción abierta. (Hay otros, sin embargo, su probabilidad es rara, consulte la documentación para obtener más información).
  5. datname:el nombre de la base de datos a la que está conectada actualmente la conexión. En varios clústeres de bases de datos, esto puede ayudar a aislar las conexiones problemáticas.
  6. wait_event_type y wait_event:estas columnas serán nulas cuando una consulta no esté esperando, pero si está esperando, contendrán información sobre por qué la consulta está esperando, y explorar pg_locks puede identificar qué está esperando. (PostgreSQL 9.5 y anteriores solo tienen una columna booleana llamada "esperando", verdadero si está esperando, falso si no.

1.1. ¿La consulta está esperando/bloqueada?

Si hay una consulta o consultas específicas que son "lentas" o "colgadas", verifique si están esperando que se complete otra consulta. Debido al bloqueo de relaciones, otras consultas pueden bloquear una tabla y no permitir que otras consultas accedan o cambien datos hasta que se realice esa consulta o transacción.

PostgreSQL 9.5 y versiones anteriores:

SELECT * FROM pg_stat_activity WHERE waiting = TRUE;

PostgreSQL 9.6:

SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL;

PostgreSQL 10 y posterior (?):

SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL AND backend_type = 'client backend';

Los resultados de esta consulta mostrarán las conexiones que actualmente esperan en otra conexión para liberar bloqueos en una relación que se necesita.

Si la consulta está bloqueada por otra conexión, hay algunas formas de averiguar cuáles son. En PostgreSQL 9.6 y versiones posteriores, la función pg_blocking_pids() permite la entrada de un ID de proceso que se está bloqueando y devolverá una serie de ID de proceso que son responsables de bloquearlo.

PostgreSQL 9.6 y posterior:

SELECT * FROM pg_stat_activity 
WHERE pid IN (SELECT pg_blocking_pids(<pid of blocked query>));

PostgreSQL 9.5 y versiones anteriores:

SELECT blocked_locks.pid     AS blocked_pid,
         blocked_activity.usename  AS blocked_user,
         blocking_locks.pid     AS blocking_pid,
         blocking_activity.usename AS blocking_user,
         blocked_activity.query    AS blocked_statement,
         blocking_activity.query   AS current_statement_in_blocking_process
   FROM  pg_catalog.pg_locks         blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks         blocking_locks 
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
   WHERE NOT blocked_locks.GRANTED;

(Disponible en PostgreSQL Wiki).

Estas consultas apuntarán a lo que esté bloqueando un PID específico que se proporciona. Con eso, se puede tomar la decisión de eliminar la consulta o conexión de bloqueo, o dejar que se ejecute.

Paso 2:si las consultas se están ejecutando, ¿por qué tardan tanto?

2.1. ¿El planificador está ejecutando consultas de manera eficiente?

Si una consulta (o un conjunto de consultas) en cuestión tiene el estado "activo", entonces en realidad se está ejecutando. Si la consulta completa no está disponible en pg_stat_activity, obténgala de los desarrolladores o del registro de postgresql y comience a explorar el planificador de consultas.

EXPLAIN SELECT * FROM postgres_stats.table_stats t JOIN hosts h ON (t.host_id = h.host_id) WHERE logged_date >= '2018-02-01' AND logged_date < '2018-02-04' AND t.india_romeo = 569;
Nested Loop  (cost=0.280..1328182.030 rows=2127135 width=335)
  ->  Index Scan using six on victor_oscar echo  (cost=0.280..8.290 rows=1 width=71)
          Index Cond: (india_romeo = 569)
  ->  Append  (cost=0.000..1306902.390 rows=2127135 width=264)
        ->  Seq Scan on india_echo romeo  (cost=0.000..0.000 rows=1 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on juliet victor_echo  (cost=0.000..437153.700 rows=711789 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on india_papa quebec_bravo  (cost=0.000..434936.960 rows=700197 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
        ->  Seq Scan on two oscar  (cost=0.000..434811.720 rows=715148 width=264)
                Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))

Este ejemplo muestra un plan de consulta para una unión de dos tablas que también llega a una tabla particionada. Estamos buscando cualquier cosa que pueda hacer que la consulta sea lenta y, en este caso, el planificador está realizando varios análisis secuenciales en las particiones, lo que sugiere que faltan índices. Agregar índices a estas tablas para la columna 'india_romeo' mejorará instantáneamente esta consulta.

Lo que debe buscar son escaneos secuenciales, bucles anidados, clasificación costosa, etc. Comprender el planificador de consultas es crucial para asegurarse de que las consultas se realicen de la mejor manera posible. Puede leer la documentación oficial para obtener más información aquí.

2.2. ¿Están infladas las mesas involucradas?

Si las consultas aún se sienten lentas sin que el planificador de consultas señale algo obvio, es hora de verificar el estado de las tablas involucradas. ¿Son demasiado grandes? ¿Están hinchados?

SELECT n_live_tup, n_dead_tup from pg_stat_user_tables where relname = ‘mytable’;
n_live_tup  | n_dead_tup
------------+------------
      15677 |    8275431
(1 row)

Aquí vemos que hay muchas veces más filas muertas que filas vivas, lo que significa que para encontrar las filas correctas, el motor debe filtrar datos que ni siquiera son relevantes para encontrar datos reales. Un vacío/vacío lleno en esta mesa aumentará significativamente el rendimiento.

Paso 3:Verifique los registros

Si aún no se puede encontrar el problema, consulte los registros en busca de pistas.

Mensajes FATAL / ERROR:

Busque mensajes que puedan estar causando problemas, como interbloqueos o largos tiempos de espera para obtener un bloqueo.

Puntos de control

Con suerte, log_checkpoints está activado, lo que escribirá la información del punto de control en los registros. Hay dos tipos de puntos de control, cronometrados y solicitados (forzados). Si se fuerzan los puntos de control, entonces los búferes sucios en la memoria deben escribirse en el disco antes de procesar más consultas, lo que puede dar a un sistema de base de datos una sensación general de "lentitud". El aumento de checkpoint_segments o max_wal_size (dependiendo de la versión de la base de datos) le dará al puntero de control más espacio para trabajar, así como ayudará al escritor de fondo a tomar parte de la carga de escritura.

Paso 4:¿Cuál es el estado del sistema host?

Si no hay pistas en la base de datos en sí, tal vez el host en sí esté sobrecargado o tenga problemas. Cualquier cosa, desde un canal de E/S sobrecargado en el disco, un desbordamiento de memoria para el intercambio o incluso una unidad defectuosa, ninguno de estos problemas sería evidente con nada de lo que vimos antes. Suponiendo que la base de datos se ejecuta en un sistema operativo basado en *nix, aquí hay algunas cosas que pueden ayudar.

4.1. Carga del sistema

Usando 'superior', mire el promedio de carga para el host. Si el número se acerca o supera el número de núcleos en el sistema, podría tratarse simplemente de que demasiadas conexiones simultáneas llegan a la base de datos, lo que hace que se detenga para ponerse al día.

load average: 3.43, 5.25, 4.85

4.2. Memoria del sistema y SWAP

Usando 'gratis', verifique si SWAP se ha usado en absoluto. El desbordamiento de memoria a SWAP en un entorno de base de datos PostgreSQL es extremadamente malo para el rendimiento, y muchos DBA incluso eliminarán SWAP de los hosts de la base de datos, ya que un error de "memoria insuficiente" es más preferible que un sistema lento para muchos.

Si se está utilizando SWAP, un reinicio del sistema lo borrará y puede ser necesario aumentar la memoria total del sistema o reconfigurar el uso de la memoria para PostgreSQL (como reducir shared_buffers o work_mem).

[[email protected] ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7986         225        1297          12        6462        7473
Swap:          7987        2048        5939

4.3. Acceso al disco

PostgreSQL intenta hacer gran parte de su trabajo en la memoria y distribuir la escritura en el disco para minimizar los cuellos de botella, pero en un sistema sobrecargado con muchas escrituras, es fácilmente posible ver que las lecturas y escrituras pesadas hacen que todo el sistema se vuelva lento a medida que se pone al día. sobre las demandas. Discos más rápidos, más discos y canales de E/S son algunas formas de aumentar la cantidad de trabajo que se puede realizar.

Herramientas como 'iostat' o 'iotop' pueden ayudar a identificar si hay un cuello de botella en el disco y de dónde puede provenir.

4.4. Consultar los registros

Si todo lo demás falla, o incluso si no, los registros siempre deben verificarse para ver si el sistema informa algo que no está bien. Ya discutimos la verificación de postgresql.logs, pero los registros del sistema pueden brindar información sobre problemas como fallas en los discos, fallas en la memoria, problemas de red, etc. Cualquiera de estos problemas puede hacer que la base de datos actúe de manera lenta e impredecible, por lo que una buena comprensión de perfecta salud puede ayudar a encontrar estos problemas.

Descargue el documento técnico hoy Gestión y automatización de PostgreSQL con ClusterControl Obtenga información sobre lo que necesita saber para implementar, monitorear, administrar y escalar PostgreSQLDescargar el documento técnico

Paso 5 - ¿Algo que todavía no tiene sentido?

Incluso los administradores más experimentados se encontrarán con algo nuevo que no tiene sentido. Ahí es donde la comunidad global de PostgreSQL puede ayudar. Al igual que el paso n.º 0, cuanto más clara sea la información que se le dé a la comunidad, más fácilmente podrán ayudar.

5.1. Listas de correo de PostgreSQL

Dado que PostgreSQL es desarrollado y administrado por la comunidad de código abierto, hay miles de personas que hablan a través de las listas de correo para discutir innumerables temas, incluidas características, errores y problemas de rendimiento. Las listas de correo se pueden encontrar aquí, siendo pgsql-admin y pgsql-performance las más importantes para buscar ayuda con problemas de rendimiento.

5.2. IRC

Freenode aloja varios canales de PostgreSQL con desarrolladores y administradores de todo el mundo, y no es difícil encontrar una persona útil para rastrear de dónde pueden provenir los problemas. Se puede encontrar más información en la página IRC de PostgreSQL.