2ndQuadrant | PostgreSQL
Bases de Datos de Misión Crítica
  • Contacto
  • ES
    • EN
    • FR
    • IT
    • DE
    • PT
  • Soporte & Servicios
  • Descargas
    • Instaladores
      • Postgres Installer
      • 2UDA – Unified Data Analytics
    • Whitepapers
      • Caso de Negocio para Soporte PostgreSQL
      • Mejores Prácticas de Seguridad
    • Casos de Estudio
      • Migración de Bases de Datos
        • International Game Technology (IGT)
        • Healthcare Software Solutions (HSS)
        • Navionics
      • Ajustes de Rendimiento
        • BenchPrep
        • tastyworks
      • Clústeres de Bases de Datos Distribuidas
        • ClickUp
        • Agencia Espacial Europea (ESA)
        • Animal Logic
        • Telefónica del Sur
      • Actualizaciones de Bases de Datos
        • Instituto Alfred Wegener (AWI)
      • Soporte & Administración de Bases de Datos
        • Met Office
        • Agilis Systems
        • London & Partners
  • Centro de Aprendizaje Postgres
    • Webinars
      • Próximos Webinars
      • Biblioteca de Webinar
    • Whitepapers
      • Caso de Negocio para Soporte PostgreSQL
      • Mejores Prácticas de Seguridad
    • Blog
    • Formación
      • Catálogo de los Cursos
    • Casos de Estudio
      • Ajustes de Rendimiento
        • BenchPrep
        • tastyworks
      • Clústeres Distribuidos
        • ClickUp
        • Agencia Espacial Europea (ESA)
        • Telefónica del Sur
        • Animal Logic
      • Administración de Bases de Datos
        • Agilis Systems
      • Formación Profesional
        • Met Office
        • London Partners
      • Actualizaciones de Bases de Datos
        • Instituto Alfred Wegener (AWI)
      • Migración de Bases de Datos
        • International Game Technology (IGT)
        • Healthcare Software Solutions (HSS)
        • Navionics
    • Libros
      • PostgreSQL 11 Administration Cookbook
      • PostgreSQL 10 Administration Cookbook
      • PostgreSQL High Availability Cookbook – 2a Edición
      • PostgreSQL 9 Administration Cookbook – 3a Edición
      • PostgreSQL Server Programming Cookbook – 2a Edición
      • PostgreSQL 9 Cookbook – Edición en Chino
    • Videos
    • PostgreSQL
      • PostgreSQL – La historia
      • ¿Quién usa PostgreSQL?
      • Preguntas Frecuentes sobre PostgreSQL
      • PostgreSQL VS MySQL
      • Caso de Negocio para PostgreSQL
      • Información de Seguridad
      • Documentación
  • Sobre nosotros
    • Sobre 2ndQuadrant
    • La Pasión de 2ndQuadrant por PostgreSQL
    • Noticias
    • Trabaje con Nosotros
  • Blog
  • Instaladores
  • Menú Menú
Usted está aquí: Inicio1 / Blog2 / Shaun's PlanetPostgreSQL3 / PG Phriday: 10 cosas que Postgres podría mejorar – Parte 3
Shaun Thomas

PG Phriday: 10 cosas que Postgres podría mejorar – Parte 3

noviembre 8, 2020/0 Comentarios/en Shaun's PlanetPostgreSQL /por Shaun Thomas

A la base del blog "10 cosas que odio de PostgreSQL", se encuentra una observación específica que a primera vista podría interpretarse como una simple molestia. MVCC aparece sólo como el número 4 de la lista, pero al igual que los XID, actúa como una estrella en la que convergen toda una constelación de objetos estelares relacionados. Mientras que la replicación (tanto física como lógica) es una parte importante del futuro de Postgres, MVCC es en gran medida su pasado y su presente, pese a algunos contratiempos a lo largo del camino.

En este post iremos directamente al corazón pulsante de Postgres para analizar detenidamente cómo maneja el almacenamiento. Este artículo no pretende ser un tratado exhaustivo sobre MVCC; existen mejores lugares para obtener esa información. Pero, lo que sabemos sobre Postgres y el almacenamiento de datos en general, nos permite identificar posibles áreas problemáticas.

Y quién sabe, puede que incluso nos quedemos agradablemente sorprendidos.

Una baraja apilada de forma perpetua

Imagínense una baraja, cuyas cartas, ordenadas según un criterio específico, deben permanecer perpetuamente en esa configuración. Si alguien toma una carta, tiene que volver a colocarla exactamente donde se encontraba. Tras unos cuantos de estos cambios, la carta se vuelve inservible y debe ser reemplazada por una nueva del mismo palo y cara.

Definitivamente no es así como funciona MVCC en Postgres. En lugar de reemplazar la carta de inmediato, simplemente colocamos una nueva en la parte superior de la baraja y dibujamos una gran X sobre la vieja carta para que todos sepan que deben ignorarla. Tal vez con el tiempo añadamos una nueva carta, y en ese momento reemplazaremos de forma aleatoria una carta previamente «cancelada».

Sin duda, este es un enfoque extremadamente eficiente en muchos sentidos. La carta existente sigue ahí, en caso de que la necesitemos. Puede que, al final, la nueva carta contenga algún error de impresión. Prácticamente, la carta vieja será visible para cualquiera hasta que la tachemos con la X. ¿Existe algún aspecto negativo en este método?

Cambios continuos

Estos constantes cambios presentan dos efectos colaterales:

  1. La cantidad de cartas «extra» en la baraja se ve limitada únicamente por la frecuencia con la que se reemplazan las cartas tachadas.
  2. Se pierde el orden deseado de las cartas en el momento en que se descarta la primera.

Postgres soluciona el primer problema con el comando VACUUM y con el correspondiente servicio autovacuum que funciona en segundo plano. La configuración por defecto añade esencialmente alrededor de un 20% de espacio extra, el cual representa un punto de equilibrio estable entre la cantidad de datos entrantes y salientes.

Es este cambio el que puede eventualmente transformar nuestra baraja, previamente mezclada, en un resultado aleatorio muy poco parecido al original. También es la razón por la que algunos usuarios expresan su frustración con respecto al almacenamiento de datos en Postgres.

Índice como Heap

Sin embargo, esta clase de barajada no es algo muy común. Aunque los usuarios de Postgres lo den por sentado, no todos los motores de bases de datos implementan una separación tan fuerte entre los roles del heap y del índice. Claro, Postgres ofrece la posibilidad de escanear únicamente los índices, y permite trabajar con ellos utilizando la sintaxis INCLUDE (). De todas formas, el heap y el índice siempre están separados. Y aunque en determinadas ocasiones podemos evitar recurrir al heap, pero es imprescindible que exista.

«10 cosas que odio de PostgreSQL» básicamente lo describió como un desperdicio de espacio. En realidad, la queja iba mucho más allá. Como hemos señalado anteriormente, en el mejor de los casos el orden del heap es poco fiable. Por consiguiente, usar el comando CLUSTER para ordenar el contenido de una tabla en función de un índice específico resulta una medida temporal, a menos que la tabla sea enteramente estática.

Suponiendo que no existan cláusulas de ordenamiento, obtener filas del heap resulta ser la acción más sencilla, ya que puede hacerse de forma secuencial. En el caso de que el índice es el heap, y en ausencia de parámetros de ordenamiento, no tenemos que seguir las referencias de los nodos índice. Los resultados ordenados requieren el uso del índice clustered, uno de los índices secundarios, o del ordenamiento en memoria. Así que todas nuestras operaciones habituales funcionan de la manera esperada.

Cuando no existe una restricción de unicidad, las bases de datos que utilizan este enfoque imponen un tipo de atributo de unicidad permanente vinculado al identificador de fila. Aunque no pueden utilizarse para las claves foráneas, constituyen un perfecto sustituto hasta disponer de un índice único más adecuado. En este caso, la tabla actuaría de forma casi idéntica al heap de Postgres.

¿Existen inconvenientes con este tipo de enfoque? Se podría discutir sobre el uso del heap como copia de datos «prístina» (sin la influencia de algoritmos interpretativos de agrupación y paginación) para la creación de otros objetos. Con el índice fuera del heap, es posible corregir casos aislados de corrupción de los datos mediante una simple reconstrucción del índice. Por otra parte, también puede producirse ese tipo de corrupción en el heap.

Quizás esto sea simplemente un anacronismo que ha sido incorporado al motor en términos de impulso. Desde la introducción del almacenamiento de tabla enchufable en Postgres 12, existe el potencial para corregir por lo menos este descuido sin tener que recurrir enteramente a Zheap.

Compresión en línea

Contrariamente a la creencia popular, el almacenamiento TOAST en Postgres no consiste en «almacenar datos comprimibles en una ubicación externa». De hecho, existen varios umbrales y mecanismos configurables para manejar la compresión. En este caso, nos remitiremos a la documentación de TOAST para explicar por qué este aspecto es relevante.

Cabe destacar la función del tipo de almacenamiento de tupla denominado MAIN , el cual intentará comprimir el valor de la columna y almacenarlo en línea con el resto de los datos de la tupla presentes en el heap. Si esta compresión excede el tamaño de la página de Postgres (8 KB), el contenido de la columna será almacenado externamente. En el caso de los objetos trivialmente comprimibles, el almacenamiento MAIN puede evitar costosas búsquedas externas en la tabla TOAST.

De todos modos, es cierto que Postgres no admite lo que algunos denominan compresión «a nivel de bloque». Esto significa que no existe un algoritmo que pueda contraer valores idénticos compartidos entre las tuplas convirtiéndolos en referencias dentro de una página. Para las tablas que contienen muchos valores repetidos como fechas, referencias de claves foráneas, etc., esto puede resultar en un considerable ahorro de espacio.

En cierto sentido, esta es la consecuencia lógica de que Postgres dependa de un almacenamiento heap natural y no interpretado como capa de datos básicos. El heap no es más que una serie de registros de tupla que caben en una página de 8 KB, excepto por las limitaciones del factor de relleno. Una vez que inyectamos efectos de compresión entre tuplas, se convierte más en un tipo de almacenamiento de índices. Por otra parte, siempre y cuando restrinjamos la compresión a una sola página, cada página leída podría pasar a través de la capa transparente de descompresión en línea antes de que el resto del motor interactúe con ella.

En este caso, el principal inconveniente es que, esencialmente se alteraría el formato de almacenamiento de Postgres de tal manera que la actualización requeriría un volcado/recuperación entre versiones. Como alternativa, puesto que los archivos comprimidos serían fácilmente distinguibles, las tablas podrían simplemente marcarse como UNCOMPRESSED hasta su posterior modificación con algún tipo de declaración ALTER TABLE.

En casos como este, puede que se trate simplemente de la falta de demanda para esa característica. Por lo tanto, la respuesta de la comunidad suele ser: «bienvenidas las revisiones».

VACUUM como ‘recolector de basura’

Este tema nos lleva a la necesidad de implementar de forma efectiva la integridad del heap. A primera vista, el concepto de VACUUM en sí mismo es muy sencillo: consiste en marcar las filas obsoletas como espacio reutilizable. Sin embargo, las complejas operaciones que realiza, los controles que regulan su comportamiento, y los detalles correspondientes, son suficientes para desconcertar incluso a los profesionales más experimentados.

Considere la necesaria tarea de congelar las filas. El ID de transacción de las tuplas visibles que contengan una referencia XID obsoleta, terminará siendo negado por un atributo de encabezamiento de fila que marcará la fila como congelada. Esto permite el movimiento continuo del horizonte XID a 32 bits de Postgres que esencialmente elimina los ID de transacción que ya no son relevantes para la visibilidad de la sesión corriente.

Pero FREEZE y VACUUM, aunque se relacionan de forma tangencial debido a la inherente manipulación de la visibilidad de las filas, no son en absoluto la misma cosa. Pese a esto, no existe un comando FREEZE independiente. Por lo tanto, esta crítica tarea de mantenimiento se encuentra detrás de una especie de paywall, ya que no puede desvincularse del proceso de recolección de las tuplas muertas.

Entonces, ¿cómo configuramos los diversos controles de vacuum para asegurarnos, entre otras cosas, de que el proceso de congelamiento se produzca a tiempo? Ese tema por sí solo puede ser (y de hecho ha sido) el tema de varios posts de blog, artículos y webinars. Managing Freezing in PostgreSQL de Andrew Dunstan constituye un buen resumen, al igual que el webinar Tuple Freezing & Transaction Wrap around Through Pictures co-presentado por Andrew Dunstan (de nuevo) y Tom Kincaid. Hay también Autovacuum Tuning Basics, otro post de Tomas Vondra que analiza más a fondo cómo establecer parámetros de configuración específicos.

La gran cantidad de información disponible es en realidad parte de la espada de doble filo. Es un tema profundo y variado que debe ser entendido con gran exactitud, para evitar que alguna mala interpretación conduzca a una sobrecarga de IO en el disco o a una limpieza irregular. Las configuraciones inadecuadas pueden llevar a un sobreconsumo de espacio en el disco o incluso al riesgo de un XID wraparound. Por otra parte, configuraciones demasiado ambiciosas pueden ocasionar una sobrecarga perjudicial en el almacenamiento.

En definitiva, un usuario de Oracle (por ejemplo) siempre considerará esto como un defecto de diseño. Cualquier tipo de mantenimiento que puede aplazarse conlleva el riesgo de problemas de planificación y consideraciones sobre el rendimiento. Además, es necesario encontrar un prudente equilibrio para prevenir los efectos intrínsecos de la sobrecarga y mantener las estructuras funcionales. Con ese fin, existe la opinión de que una estructura de datos que no requiera este tipo de mantenimiento constante, en algunos casos de uso resulte superior.

En realidad, Postgres implementa varias optimizaciones que facilitan el mantenimiento. Si se congelan todas las tuplas de una página, la misma quedará totalmente marcada. Esto puede acelerar enormemente las operaciones de congelamiento de la tabla. Combinado con las habituales invocaciones por medio de autovacuum,  en la mayoría de los sistemas la sobrecarga resultaría casi indistinguible del ruido de fondo.

Las complejidades del almacenamiento

En muchos sentidos, esta es una discusión filosófica. La decisión inicial de desvincular el heap y los incrementos externos (como los índices) puede haber comenzado como una limitación técnica. Sin embargo, otros motores de bases de datos han demostrado claramente que esta distinción no es necesaria y que puede carecer de muchos beneficios implícitos. De hecho, una mejora que aún no hemos mencionado es que una capa integrada de índice/heap reduciría drásticamente el tráfico del WAL.

En el enfoque de Postgres respecto a MVCC incide el costo de mantenimiento. Sin embargo, a diferencia de los segmentos de reversión que son commit-optimistic, las tuplas de Postgres son transaction agnostic en reposo. Todo lo que Postgres en todo momento necesita saber es si una transacción está comprometida (committed) o no. Los motores de bases de datos que dependen de mecanismos externos de reversión deben volver a colocar físicamente las filas revertidas en el almacenamiento de tabla para que puedan ser utilizadas. Esto hace que, en comparación, la recuperación tras una caída sea extremadamente costosa y lenta.

Sin embargo, sería genial poder contar con la compresión de bloques en línea. Asumiendo que el motor interactúe exclusivamente con la página descomprimida, únicamente las operaciones de lectura y escritura tendrían que preocuparse de las llamadas de compresión. Entre los diferentes temas que hemos abordado, esta es probablemente una de las modificaciones más fáciles de realizar. Definitivamente es mucho más sencillo que reemplazar el sistema de almacenamiento heap por un índice-heap híbrido.

Aún así, estas son las razones por las que cualquier DBA de Postgres debería familiarizarse con la implementación de MVCC. Determinan qué tipo de mantenimiento es necesario y por qué lo es. Nos explican exactamente cómo Postgres interactúa con los datos que almacena. Basándonos en estas razones, podemos entender las limitaciones y los puntos de fuerza implícitos. Es poco probable que detalles esotéricos como este sean elementos clave absolutamente decisivos.

A pesar de que Postgres haya aprovechado considerablemente sus fortalezas, todavía hay margen para mejorar. En última instancia, sólo el tiempo dirá en qué dirección irán las cosas.

Etiquetas: indexes, mvcc, PG Phriday, Pluggable Storage, Vacuum, XID
Compartir esta entrada
  • Compartir en Facebook
  • Compartir en Twitter
  • Share on WhatsApp
  • Compartir en LinkedIn
/wp-content/uploads/2019/04/2ndQuadrant-Logo-e1554357894467.png 0 0 Shaun Thomas /wp-content/uploads/2019/04/2ndQuadrant-Logo-e1554357894467.png Shaun Thomas2020-11-08 16:47:362020-11-08 16:47:36PG Phriday: 10 cosas que Postgres podría mejorar – Parte 3
0 comentarios

Dejar un comentario

¿Quieres unirte a la conversación?
Siéntete libre de contribuir!

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Search

Get in touch with us!

Recent Posts

  • PG Phriday: 10 cosas que Postgres podría mejorar – Parte 3 noviembre 8, 2020
  • Búsqueda de texto completo desde PostgreSQL 8.3 noviembre 5, 2020
  • Webinar: Mejores prácticas para la carga masiva de datos en PostgreSQL [continuación] noviembre 4, 2020
  • Números aleatorios noviembre 4, 2020
  • ¿Qué partición de mi base de datos PostgreSQL contiene una fila determinada? noviembre 1, 2020

Featured External Blogs

Tomas Vondra's Blog

Our Bloggers

  • Simon Riggs
  • Alvaro Herrera
  • Andrew Dunstan
  • Craig Ringer
  • Francesco Canovai
  • Gabriele Bartolini
  • Giulio Calacoci
  • Ian Barwick
  • Marco Nenciarini
  • Mark Wong
  • Pavan Deolasee
  • Petr Jelinek
  • Shaun Thomas
  • Tomas Vondra
  • Umair Shahid

PostgreSQL Cloud

2ndQuadrant ANALYZE autoanalyze AutoVacuum benchmarking best practice bulk insert community data import data load EDB full text search GIN GIST indexes java JSON JSONB jsonpath mvcc OmniDB open source Partitioning partitions performance pgbench PG Phriday Pluggable Storage postgres PostgreSQL PostgreSql analyze postgresql vacuum prng pseudorandom number generators r2dbc RUM tableoid TPC-H TPCH Vacuum vacuuming VODKA webinars XID
  • Twitter
  • Linkedin
  • Facebook
  • Youtube
  • Mail

Soporte y Servicios

Soporte de producción 24/7

Soporte para desarrolladores

DBA remoto para PostgreSQL

Monitoreo para bases de datos PostgreSQL

Health Check para PostgreSQL

Ajustes de Rendimiento para PostgreSQL

Auditoría de seguridad para bases de datos

Actualice PostgreSQL

Evaluación de Migración hacia PostgreSQL

Migre desde Oracle

Productos

PostgreSQL de alta disponibilidad

BDR

2ndQPostgres

pglogical

repmgr

Barman

Postgres Cloud Manager

Firewall SQL

Postgres-XL

OmniDB

Postgres Installer

2UDA

Centro de Aprendizaje Postgres

PostgreSQL

Blog

Webinars

Libros

Videos

Formación

Casos de Estudio

Eventos

Sobre nosotros

Sobre 2ndQuadrant

¿Qué significa «2ndQuadrant»?

Noticias

Trabaje con nosotros

Nuestro equipo

© 2ndQuadrant Ltd. All rights reserved | Privacy Policy
  • Twitter
  • LinkedIn
  • Facebook
  • Youtube
  • Mail
Búsqueda de texto completo desde PostgreSQL 8.3
Desplazarse hacia arriba
×