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

PostgreSQL:seis piezas no tan fáciles

PostgreSQL viene con un excelente conjunto de funciones, incomparable en el espacio RDBMS de código abierto. En su mayoría, es fácil de aprender y usar, especialmente para los desarrolladores de aplicaciones. Sin embargo, algunas partes, bueno, simplemente no son fáciles. Requieren trabajo para configurarlos y hacerlo bien, y también suelen ser de misión crítica.

Administración de conexiones

PostgreSQL lanza un nuevo proceso, llamado proceso backend , para manejar cada conexión. Esto contrasta con las modernas arquitecturas de manejo de conexiones basadas en bucles de eventos/grupos de subprocesos que se encuentran en otro software de servidor comparable. Generar un proceso completo requiere más tiempo y recursos, y se manifiesta como latencias de consulta aumentadas en aplicaciones donde las conexiones se abren y cierran a una velocidad alta.

En la mayoría de las implementaciones, se requiere agrupación de conexiones en algún nivel. En el nivel de una aplicación, esto puede ser utilizando las características de su lenguaje de programación/biblioteca. Por ejemplo, sql/DB.SetMaxIdleConns puede usarse para aumentar la reutilización de la conexión desde una sola aplicación Go.

Sin embargo, a menudo tendrá que usar una solución de equilibrio de carga o agrupación de conexiones de terceros. Los agrupadores de conexiones mantienen un grupo de conexiones inactivas con el servidor Postgres ascendente, que se asignan y se envían a las conexiones de clientes entrantes. Por lo general, analizan el SQL enviado por los clientes para reconocer los límites de las transacciones y los DML de modificación de datos para implementar características como la agrupación de conexiones a nivel de transacción y las réplicas de lectura.

PgBouncer es un agrupador popular, liviano y de conexión binaria única y, a menudo, se ejecuta junto con PostgreSQL en el mismo sistema.

PgPool es más versátil que PgBouncer. También puede equilibrar la carga y replicar, por ejemplo.

Sin embargo, la agrupación de conexiones trae su propio conjunto de dolores de cabeza. En primer lugar, es una parte móvil adicional que se ha mantenido en su despliegue. Configurar la autenticación también es una molestia si tiene clientes que usan diferentes credenciales o mecanismos de autenticación. Algunas características de nivel de conexión como LISTEN/NOTIFY, declaraciones preparadas, tablas temporales y similares pueden requerir una configuración adicional o cambios en el lado del cliente para funcionar.

Actualizaciones sin tiempo de inactividad

La actualización de PostgreSQL entre versiones menores (13.x -> 13.y) implica la instalación del nuevo paquete y el reinicio del proceso del servidor. Si bien reiniciar el proceso del servidor interrumpirá necesariamente a todos los clientes conectados, sigue siendo una pregunta razonable, dado que el tiempo de inactividad está vinculado a la duración del reinicio del servicio.

Sin embargo, la actualización entre versiones principales (12.x -> 13.y) es mucho más importante. Por lo general, cuantos más datos hay, más doloroso es el proceso.

El método más simple, que funciona solo para pequeñas cantidades de datos (digamos decenas de GB), es volcar los datos de la versión anterior y restaurarlos en un servidor de nueva versión. Otra opción es usar pg_upgrade, que requiere un baile orquestado. involucrando binarios de ambas versiones de Postgres.

En cualquier caso, las bases de datos estarían inactivas durante un tiempo considerable.

Idealmente, debería ser posible replicar a un servidor de nueva versión y promocionar el servidor de nueva versión como servidor principal. Sin embargo, no es posible hacer una replicación de transmisión a un servidor en espera con una versión principal diferente. La replicación lógica, aunque parece adecuada para el trabajo, tiene ciertos inconvenientes que deben solucionarse para garantizar una replicación completa.

La mayoría de las soluciones HA para Postgres se basan en la replicación de transmisión y, por lo tanto, no puede actualizar los nodos en un clúster de uno en uno.

El estado actual del arte sería usar la replicación lógica, mientras se solucionan las limitaciones de la replicación lógica y posiblemente implique funciones de restricción que las aplicaciones pueden usar (como DDL) durante la fase de actualización.

Alta disponibilidad

PostgreSQL viene con todas las funciones de bajo nivel necesarias para construir una solución HA:replicación con retroalimentación, replicación en cascada, replicación síncrona, esperas, esperas activas, promoción de espera, etc. Sin embargo, en realidad no proporciona una solución HA lista para usar. No hay marcos ni herramientas para monitorear el estado y la conmutación por error automática a un modo de espera. No existe la noción de un clúster HA de varios nodos.

Tendrá que configurar y ejecutar una solución de terceros para crear implementaciones de Postgres de alta disponibilidad. Los favoritos actuales sonpg_auto_failover y Patroni. Mientras que Patroni se basa en un almacén de configuración existente de alta disponibilidad como ZooKeeper o etcd, pg_auto_failover puede prescindir de uno.

Evaluar, implementar y probar uno de estos en producción requiere tiempo y esfuerzo. Se deben configurar y mantener libros de estrategias de monitoreo, alertas y operaciones.

Gestión de la hinchazón

La arquitectura MVCC de PostgreSQL significa que nunca se sobrescribe ningún dato; la modificación de una fila solo da como resultado que se escriba una nueva versión de la fila en el disco. Eliminar una fila solo significa registrar que la fila es invisible para transacciones futuras. Cuando una versión de fila es inaccesible desde cualquier transacción en curso o futura, ya no tiene ningún uso y se denomina "inflado". El proceso de recolección de basura se llama "vacío".

Bloat es invisible para las aplicaciones y se convierte únicamente en el dolor de cabeza del DBA. Para las tablas con muchas actualizaciones, monitorear y administrar el bloat es un problema no trivial. tablelevel para garantizar que los tamaños de las mesas no crezcan de manera inmanejable.

Los índices también se ven afectados por la hinchazón, y el vacío automático no ayuda aquí. La eliminación de filas y la actualización de columnas indexadas conducen a entradas muertas en los índices. Las cargas de trabajo intensivas en actualizaciones con actualizaciones de columnas indexadas pueden generar índices ineficientes y en constante crecimiento. No hay equivalente de vacío para índices. La única solución es reconstruir todo el índice usando REINDEX o usar VACUUM FULL en la tabla.

Aparte de un único valor por tabla (pg_stat_all_tables.n_dead_tup), Postgres no ofrece nada en la forma de estimar la hinchazón en una tabla, y nada en absoluto para los índices. La forma más práctica sigue siendo ejecutar una consulta aterradora desde check_postgres.

pgmetrics incorpora la consulta de check_postgres y puede producir resultados en formato JSON y CSV que incluyen información de tamaño y sobredimensión para todas las tablas e índices; que pueden incorporarse a herramientas de supervisión o automatización.

pg_repack es una alternativa popular a VACUUM FULL:puede hacer el mismo trabajo pero sin bloqueos. Si se ve obligado a hacer VACUUM FULL regularmente, es una herramienta que debe investigar.

zheap es el nuevo motor de almacenamiento para Postgres que ha estado en desarrollo durante años y que promete reducir la sobrecarga a través de actualizaciones en el lugar.

Gestión de planes de consultas

Core PostgreSQL ofrece solo dos herramientas rudimentarias en este espacio:

  • pg_stat_statements extensión para análisis de consultas:proporciona el total y los promedios de los tiempos de planificación y ejecución de consultas, uso de disco y memoria
  • auto_explain extensión, que puede imprimir planes de ejecución de consultas en el destino de registro de Postgres

Si bien las estadísticas proporcionadas por pg_stat_statements son suficientes para arreglárselas, usando auto_explain forzar planes en archivos de registro y luego extraerlos no es más que un truco, especialmente en comparación con los competidores comerciales de Postgres, que ofrecen funciones de administración, líneas base e historial de planes.

El estado actual del arte con Postgres es extraer el archivo de registro para los planes de consulta y almacenarlos en otro lugar. Pero quizás el problema más problemático es no poder asociar el plan de consulta con los análisis correspondientes de pg_stat_statements. La forma en que pgDash hace esto es analizar los textos de consulta SQL de pg_stat_statements y la salida de auto_explain, ajustar la manipulación realizada por pg_stat_statements e intentar hacer coincidir los dos. Requiere un analizador SQL de dialecto PostgreSQL completo.

La línea de base, el establecimiento de políticas para la selección de planes, etc. simplemente no son posibles actualmente en el núcleo de PostgreSQL.

Existen algunas extensiones que son básicamente versiones mejoradas de pg_stat_statements, pero los pasos adicionales involucrados en el uso de una extensión de terceros lo convierten en un desafío para la mayoría de las personas, especialmente si usan un proveedor de Postgres administrado.

Tuning

PostgreSQL tiene una plétora de opciones de ajuste, a partir de la configuración de buffers compartidos por defecto. Algunos son fáciles de entender y configurar, como el número de trabajadores paralelos para varias operaciones (max_worker_processes, max_parallel_*, etc.). Otros son un poco oscuros (wal_compression, random_page_cost, etc.) pero generalmente son beneficiosos. Sin embargo, los más molestos son los que necesitan información cuantificable sobre la carga de trabajo.

Por ejemplo, si work_mem es demasiado bajo, las consultas pueden usar archivos de disco temporales; si es demasiado alto y hay suficientes consultas simultáneas, los procesos back-end de Postgres pueden ser eliminados por OOM. Entonces, ¿cómo averiguas en qué número configurarlo?

En la práctica, especialmente con cargas de trabajo de OLTP y cargas de trabajo de aplicaciones web, es imposible predecir cuál sería la demanda máxima de memoria para las consultas. Lo mejor que puede hacer es establecer un valor razonable y luego controlar las consultas para ver si alguna de ellas podría haberse beneficiado de un valor más alto de work_mem.

¿Y cómo haces eso? Deberá obtener la extensión auto_explain para registrar los planes de ejecución de consultas de cada consulta, extráigalos de los archivos de registro de Postgres, examine cada plan de consulta para ver si utiliza fusiones externas basadas en disco o un escaneo de montón de mapa de bits con bloques de montón con pérdida.

No imposible, simplemente difícil.