1 puntos por GN⁺ 2025-12-24 | 1 comentarios | Compartir por WhatsApp
  • PostgreSQL 18 puede clonar bases de datos casi al instante al combinar la estrategia de copia de archivos (FILE_COPY) con la función de clonación del sistema de archivos
  • Con la nueva configuración file_copy_method = clone, es posible aprovechar la función de clonación de sistemas de archivos modernos (FICLONE) como XFS, ZFS y APFS
  • Según los benchmarks, al clonar una base de datos de 6 GB, el método tradicional WAL_LOG tarda unos 67 segundos, mientras que el método con clonación lo reduce a alrededor de 0.2 segundos
  • La base de datos clonada comparte inicialmente los mismos bloques físicos, pero se separa mediante copy-on-write cuando hay operaciones de escritura
  • Sin embargo, solo se puede clonar cuando no hay conexiones activas y existe la restricción de que solo funciona dentro de un mismo sistema de archivos

Estructura de clonación basada en plantillas en PostgreSQL

  • En PostgreSQL, al ejecutar el comando CREATE DATABASE dbname, internamente se clona la base de datos template1 para crear una nueva base de datos
    • Esto equivale al comportamiento de CREATE DATABASE dbname TEMPLATE template1
  • En lugar de template1, se puede especificar otra base de datos, por lo que es posible clonar usando plantillas personalizadas
  • En PostgreSQL 18, este sistema de plantillas se amplió a una estructura capaz de clonación instantánea

CREATE DATABASE ... STRATEGY

  • Desde PostgreSQL 15 se introdujo el parámetro CREATE DATABASE ... STRATEGY, que permite elegir el método de clonación
    • El valor predeterminado es WAL_LOG, que realiza una clonación por bloques mediante Write-Ahead Log
    • Este método reduce la carga de I/O y mejora el soporte de concurrencia, pero es más lento al clonar grandes volúmenes de datos
  • Si se especifica STRATEGY=FILE_COPY, se puede volver al método tradicional de copia de archivos y, en PostgreSQL 18, sobre esa base se añadió una nueva opción de clonación

FILE_COPY y file_copy_method

  • La configuración file_copy_method de PostgreSQL 18 controla el método de copia de archivos a nivel del sistema operativo
    • El valor predeterminado es copy, que lee todos los bytes y los escribe en una nueva ubicación
    • Si se cambia a clone, se usa la función de clonación del sistema de archivos (FICLONE) para lograr clonación instantánea sin consumo adicional de espacio
  • Sistemas de archivos compatibles: XFS, ZFS, APFS, FreeBSD ZFS
  • Procedimiento de configuración
    • Configurar el clúster de PostgreSQL sobre uno de esos sistemas de archivos
    • Establecer file_copy_method = clone y recargar la configuración

Resultados del benchmark

  • Tras crear una base de datos de prueba de unos 6 GB (source_db), se compararon dos métodos
    • Método WAL_LOG: 67,000 ms (unos 67 segundos)
    • Método FILE_COPY + clone: 212 ms
  • Con el mismo volumen de datos, se confirmó una mejora de velocidad de más de 300 veces
  • La base de datos clonada (fast_clone) casi no usa espacio adicional en disco

Cómo funciona internamente la data clonada

  • Al usar file_copy_method = clone, solo se clona el metadato del sistema de archivos, por lo que ambas bases de datos comparten los mismos bloques físicos
  • El tamaño de la base de datos que reporta PostgreSQL sigue siendo el tamaño lógico (unos 6 GB)
  • Cuando se producen escrituras, entra en acción copy-on-write (COW) y se separan las páginas correspondientes
    • Páginas que contienen filas modificadas
    • Páginas donde se escriben nuevas tuplas
    • Páginas de índices, FSM y visibility map, entre otras
  • Incluso al ejecutar VACUUM se producen separaciones adicionales de páginas

Verificación de bloques compartidos en XFS

  • Con el comando filefrag -v se puede comprobar si dos bases de datos comparten bloques físicos
    • En el estado inicial, todos los extents aparecen marcados como shared
    • Si se actualizan algunas filas, los primeros 40 bloques (unos 160 KB) se separan y pasan a direcciones físicas diferentes
    • Los demás extents siguen compartidos

Precauciones y restricciones

  • No debe haber conexiones activas a la base de datos origen al momento de clonar
    • Esta es una restricción de PostgreSQL, no un problema del sistema de archivos
    • En entornos de producción, lo habitual es usar una base de datos de plantilla separada
  • Solo se puede clonar dentro de un mismo sistema de archivos
    • Si varios tablespaces están en distintos puntos de montaje, se usará copia normal en su lugar
  • En servicios administrados en la nube (AWS RDS, Google Cloud SQL, etc.) no se puede usar esta función porque no hay acceso al sistema de archivos
    • En entornos con VM propia o bare metal sí es posible tener control total

Conclusión

  • La función file_copy_method = clone de PostgreSQL 18 aprovecha directamente la clonación a nivel del sistema operativo para
    reducir drásticamente el tiempo de clonación de grandes bases de datos
  • Hace posible implementar flujos de trabajo con bases de datos que se clonan y reinician al instante en entornos de prueba, desarrollo y aprendizaje
  • Aun así, se necesita un diseño operativo que tenga en cuenta la restricción de conexiones activas y la necesidad de un solo sistema de archivos

1 comentarios

 
GN⁺ 2025-12-24
Comentarios en Hacker News
  • Para quienes no pueden esperar o necesitan aislamiento completo de instancias en PG18, hice Velo, una herramienta que crea ramas al instante usando snapshots de ZFS
    Funciona con cualquier versión de PostgreSQL y cada rama tiene su propio contenedor y puerto
    Puede crearse en unos 2 a 5 segundos para una DB de 100 GB
    La diferencia frente al enfoque de PG18 es que no comparte una sola instancia, sino que ofrece aislamiento total del servidor
    Enlace a GitHub

    • En otro comentario se quejaban del uso de Claude Code, pero vi el video de demostración en la página de GitHub y me pareció interesante
    • Hoy en día la mayor parte del software se escribe con ayuda de agentes de IA, así que no entiendo por qué se quejan. El enfoque me parece interesante
    • Yo también estaba por prototipar algo parecido con btrfs
    • Me pareció interesante el uso de “tú”, así que me sorprendió un poco ver que decían que era plagio
  • Hace tiempo, cuando mi empresa migró a RDS, armamos internamente un sistema parecido
    Como durante las migraciones a producción surgían problemas con frecuencia, automatizamos los siguientes pasos para evitarlos

    1. clonar la DB de RDS o crear una nueva instancia desde un respaldo
    2. extraer el CNAME o la IP pública a partir del ARN
    3. reflejarlo en la configuración de conexión a la DB de la app
    4. ejecutar la migración en un entorno falso de producción
      Gracias a este proceso pudimos detectar muchos bugs específicos de producción que no aparecían ni en local ni en CI
      Después lo automatizamos con un simple script de Ruby, y escuché que todavía lo siguen usando
    • Yo también odio esos bugs de “la migración solo falla en producción por particularidades de los datos”. Más de una vez tuve que cancelar un release por eso
  • Recién me entero de que la estrategia de clonado desde plantilla es configurable
    Yo usé Neon para crear entornos de integración en tiempo real, y en mi proyecto de Golang pgtestdb se crea una DB de Postgres con todas las migraciones de esquema aplicadas para cada prueba
    Hace tiempo vi en una startup que usaban btrfs para crear DBs de staging al instante, y me parece interesante cómo reaparece la misma idea
    Este tipo de clonado rápido y pruebas es una gran ventaja de Postgres y Sqlite, y ojalá también existiera en Clickhouse o MySQL

  • Últimamente PostgreSQL parece haberse convertido en una DB todoterreno que cubre casi todos los usos de SQL
    Y además es gratis
    Me pregunto si todavía hay alguna razón real para usar otra DB SQL

    • Postgres es excelente, pero en MySQL la replicación master-master es más sencilla, y en MongoDB la distribución geográfica y el sharding son más simples
      Clickhouse es muchísimo más rápido para analítica, y DBs como Cassandra son mejores para cargas centradas en escritura
      En otras palabras, cada DB sigue teniendo sus fortalezas
    • Decir que “hace todo bien” es una exageración
      Cuando los datos crecen, aparecen degradación de rendimiento y problemas de migración
      En mi caso, el rendimiento del particionado nativo era malo y tuve que implementar particiones personalizadas por mi cuenta
    • Postgres sigue teniendo una implementación de MVCC (copy-on-write) poco eficiente
      Esa decisión trae varios efectos negativos cuando la carga aumenta
    • Antes, MySQL/InnoDB era mejor para cargas centradas en actualizaciones
      Es un tema que también se trató en el blog de Uber
      Aun así, en la nube sigo confiando más en Postgres
    • Postgres todavía no tiene una alternativa con la madurez de Vitess
      Por eso, en despliegues grandes de OLTP, MySQL sigue usándose mucho (por ejemplo, YouTube y Uber)
  • Si se usan estructuras de datos inmutables (HAMT), se puede construir una DB con clonación instantánea sin importar el tipo de sistema de archivos
    Dijeron que era teoría, pero yo realmente lo implementé
    No entiendo por qué no hay más DBs basadas en HAMT

    • Yo soy el autor de ClickHouse, y ClickHouse también usa partes de datos inmutables para permitir la clonación de tablas
      Enlace a la documentación relacionada
    • Me pregunto si Datomic también trae esta función de clonado integrada. Hace tiempo quiero probarlo, pero todavía no me siento listo para crear una app real con eso
  • No sabía que en Postgres v15 WAL_LOG pasó a ser el valor por defecto
    En entornos de pruebas paralelas en CI, tiene más sentido volver a la estrategia FILE_COPY
    Abrí un issue relacionado en mi proyecto anterior integresql

  • Hace tiempo hice una herramienta GUI simple pgtt para probar apps basadas en Postgres en local
    Simplifica mucho la configuración del entorno de desarrollo

    • Solo con el README no me queda claro, pero me pregunto si la estructura trata las plantillas como snapshots
      Parece que ayudaría con el trabajo repetitivo de las migraciones SQL
    • Estaría bueno que el README tuviera una captura de pantalla del GUI, y el enlace de Docker está roto
  • Leí otros artículos del blog y en general son excelentes
    En particular, fue la primera vez que supe de los tipos range de Postgres

    • Los tipos range son realmente útiles para cosas como calcular solapamientos de intervalos de tiempo/fechas
  • Me pregunto si MariaDB también tiene algo así
    Me preocupa que sea lento devolver la DB a su estado inicial en cada prueba
    Como usamos MariaDB en producción, es difícil cambiar de DB
    Aunque la opción de Postgres sí parece mejor

    • Si ejecutas cada prueba dentro de una sesión transaccional y haces rollback al final, puedes restaurar rápido el estado inicial
      Es un método bastante eficiente
    • Si no te molesta reiniciar la DB, otra opción es usar LVM o snapshots de btrfs a nivel de sistema de archivos
  • AWS también ofrece una función similar
    Documentación de clones de Aurora

    • Los clones de Aurora funcionan con copy-on-write a nivel de almacenamiento, pero igual hay que aprovisionar un clúster nuevo, así que tarda unos 10 minutos
      Para pruebas de integración no es realista
    • Aurora clona a nivel de clúster, mientras que aquí se está hablando de clonación a nivel de base de datos