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.
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.
Las columnas notables en pg_stat_activity son:
- 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.
- 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.
- 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).
- 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).
- 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.
- 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;
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écnicoPaso 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.