Después de conocer Deltalake y Apache Hudi en publicaciones anteriores, en este blog cerramos la tríada de formatos abiertos de tablas con Apache Iceberg. Originalmente desarrollado en Netflix y ahora convertido en un proyecto de nivel superior dentro de Apache, Iceberg se ha consolidado como una de las opciones más populares para los data lakehouses modernos. Al igual que Deltalake y Apache Hudi, Apache Iceberg es un formato abierto de tabla diseñado para aportar orden y fiabilidad a los data lakes, transformando un conjunto de archivos en almacenamiento de objetos en una verdadera tabla SQL, con metadatos, evolución de esquemas y garantías transaccionales.
Sin embargo, adopta un enfoque distinto en algunas decisiones clave de diseño respecto a sus competidores. Mientras que Delta y Hudi suelen estar estrechamente ligados a motores de procesamiento (query engine) específicos (Delta con Spark, Hudi con su enfoque propio en ingesta y streaming), Iceberg fue concebido desde el inicio para ser independiente del query engine. Su especificación está estrictamente definida, lo que permite que query engines como Spark, Trino, Flink, Presto y Hive interactúen con la misma tabla sin depender de comportamientos específicos de cada query engine.
Otra diferencia radica en cómo Iceberg gestiona los metadatos y el particionado. En lugar de apoyarse en estructuras de directorios o convenciones del motor, Iceberg administra todos los metadatos en sus propios archivos. Esto permite el particionado oculto, la evolución de particiones y una planificación de consultas rápida, sin las suposiciones frágiles que derivan de diseños basados en directorios.
Iceberg se distingue por ser independiente del motor, centrado en los metadatos y amigable con la evolución — lo que lo convierte en una opción popular para equipos que buscan un formato de tabla con flexibilidad a largo plazo en plataformas de datos multi-motor. Vamos a profundizar en Iceberg para comprender todo su potencial.
Snapshots, ramas y etiquetas
Uno de los pilares de Iceberg es su modelo de versionado y viaje en el tiempo, basado en snapshots, ramas y etiquetas. Estos elementos permiten rastrear, aislar y revertir cambios de forma segura.
Un snapshot de tabla representa una vista consistente de la tabla en un momento determinado. Cada operación de escritura (insertar, actualizar, eliminar o sobrescribir) genera un nuevo snapshot. Los snapshots referencian el conjunto exacto de archivos de datos y metadatos en ese instante, lo que permite: consultar la tabla “a partir de” un snapshot anterior, revertir a un estado previo y reproducir datos históricos para depuración o auditoría. Los snapshots son inmutables y se identifican mediante un ID único, lo que los convierte en bloques confiables para construir el historial de la tabla.
Sobre los snapshots, Iceberg introduce las ramas. Piensa en ellas como Git para los datos: se puede crear una rama desde un snapshot, ejecutar experimentos o pruebas de pipelines sobre ella, sin afectar el resto de los flujos de trabajo. Esto permite a los equipos aislar cambios sin riesgo de corromper datos en producción, y abre la puerta a entornos de staging o desarrollo/pruebas que operan sobre el mismo conjunto de datos subyacente.
Finalmente, están las etiquetas, que son marcadores ligeros que se pueden adjuntar a cualquier snapshot. A diferencia de las ramas, las etiquetas no cambian — son etiquetas permanentes que se pueden usar para marcar puntos importantes en la historia, como una versión de dataset para entrenamiento de modelos de machine learning o un punto de control de auditoría.
En conjunto, los snapshots, ramas y etiquetas proporcionan a Iceberg un modelo de historial robusto. Permiten seguridad operativa y flexibilidad analítica — todo mientras se mantiene una gestión de metadatos ligera y una planificación de consultas eficiente.
Gestión de metadatos y diseño de almacenamiento
Iceberg organiza sus tablas mediante una jerarquía de metadatos en capas. Esta estructura permite manejar tablas a escala de petabytes sin escaneos lentos ni listados costosos de archivos en almacenamiento de objetos.
En la parte superior, cada tabla tiene un archivo de metadatos. Este archivo registra información de alto nivel: el esquema actual de la tabla, la especificación de particionado, propiedades y, lo más importante, un puntero al snapshot actual. Cuando ocurre un nuevo commit, Iceberg no sobrescribe este archivo; escribe una nueva versión y actualiza el puntero de forma atómica para referenciarla. Este mecanismo garantiza la atomicidad entre lectores y escritores.
Un snapshot es una vista lógica de la tabla en un momento dado. Cada snapshot se representa mediante una pequeña entrada de metadatos dentro del archivo de metadatos de la tabla, y apunta a un archivo de lista de manifiestos. Esta lista es un índice compacto de los manifiestos que pertenecen a ese snapshot.
Cada manifiesto, a su vez, lista los archivos de datos incluidos en ese snapshot. Un manifiesto no es solo un listado de archivos — también almacena estadísticas detalladas (conteo de filas, valores de partición, valores mínimos/máximos por columna, métricas a nivel de archivo). Estas estadísticas permiten a los motores de consulta omitir archivos desde el inicio, reduciendo drásticamente los costes de escaneo.
Para ilustrarlo:
- Cuando un trabajo escribe nuevos datos, se generan nuevos archivos de datos.
- Se escribe un nuevo manifiesto para rastrearlos.
- Se crea una nueva lista de manifiestos que referencia tanto los nuevos como los existentes.
- Finalmente, se realiza un commit de un nuevo archivo de metadatos que apunta al nuevo snapshot.

Este diseño garantiza la inmutabilidad en cada nivel (archivos de datos, manifiestos, listas de manifiestos), mientras que el puntero de metadatos de la tabla actúa como fuente única de verdad. Los lectores siempre saben exactamente qué archivos pertenecen a una tabla sin escanear directorios, y los escritores pueden hacer commits de forma segura mediante el intercambio atómico del puntero.
El rol del data catalog en Apache Iceberg
Una parte clave del diseño de Iceberg es su dependencia de un data catalog. A diferencia de Delta Lake o Hudi, que almacenan registros de transacciones dentro del directorio de la tabla, Iceberg requiere un catálogo que actúe como fuente autorizada del estado actual de la tabla.
En el centro de esto está el puntero del catálogo. Básicamente, el catálogo almacena la ubicación del archivo de metadatos actual de la tabla. Cada vez que se realiza un commit, Iceberg escribe un nuevo archivo JSON de metadatos de tabla (que contiene el nuevo snapshot, el esquema y la especificación de particionado). El commit se finaliza únicamente cuando el puntero del catálogo se actualiza para referenciar este nuevo archivo.
En Hive Metastore, una implementación común de data catalog, este puntero se almacena como una propiedad de la tabla en la entrada del metastore. Esa propiedad simplemente mapea el identificador de la tabla (por ejemplo, mi_base_datos.mi_tabla_iceberg
) a la ruta del archivo metadata.json
actual en el almacenamiento de objetos.
Cada commit en Iceberg genera un nuevo archivo JSON de metadatos. Para publicarlo, el escritor solicita al metastore que actualice el puntero:
UPDATE table_params
SET current_metadata = 's3://bucket/db/table/metadata/metadata-Y.json'
WHERE current_metadata = 's3://bucket/db/table/metadata/metadata-X.json';
Esto funciona como una operación de comparación e intercambio (CAS). La actualización solo tiene éxito si el puntero aún referencia el archivo de metadatos desde el cual comenzó el escritor (metadata-X.json
). Si otro trabajo hizo commit primero, el puntero ya habrá cambiado, y la actualización fallará. Entonces, el escritor reintenta leyendo los metadatos más recientes y construyendo un nuevo commit.
Este puntero es la única parte mutable del sistema. Todos los demás archivos — archivos de datos, manifiestos, listas de manifiestos y archivos de metadatos anteriores — son inmutables. Los lectores siempre consultan primero el catálogo para resolver el puntero, y luego siguen la cadena de metadatos hasta el conjunto exacto de archivos de datos que componen la tabla.
Este mecanismo es, en esencia, un control de concurrencia optimista. Los escritores no bloquean la tabla, pero solo una actualización del puntero puede tener éxito a la vez. Los lectores se benefician porque siempre ven un snapshot limpio y completamente comprometido. Esta regla simple — todos los archivos son inmutables, el puntero es la única referencia mutable — es lo que le da a Iceberg atomicidad. Los lectores siempre resuelven el estado de la tabla preguntando al catálogo cuál es el archivo de metadatos actual. Eso garantiza que vean el snapshot anterior o el nuevo, pero nunca un estado a medio escribir.
Aquí explicamos los detalles de implementación con Hive Metastore, pero el catálogo puede implementarse en varios backends (AWS Glue, bases de datos JDBC o el catálogo REST de Iceberg). Aunque difieren en la implementación, el principio es el mismo: el puntero es la única referencia mutable que define el estado activo de la tabla, y se actualiza de forma atómica cuando se crean nuevos snapshots.
En contraste, Delta Lake mantiene su registro de transacciones en archivos _delta_log
dentro del directorio de la tabla, y Hudi hace algo similar con su carpeta .hoodie
. Iceberg separa deliberadamente estas responsabilidades: los metadatos inmutables capturan el historial, mientras que el puntero del catálogo proporciona coordinación y atomicidad.
Evolución de la tabla: esquema y particionado oculto
Evolución del esquema
Una de las funcionalidades destacadas de Iceberg es su manejo robusto de cambios en el esquema. A diferencia de los formatos tradicionales de tabla que dependen del orden o nombre de las columnas, Iceberg asigna un ID único a cada campo de la tabla. Este ID permanece constante incluso si la columna se renombra, se elimina o se promueve su tipo de forma compatible. Por ejemplo, renombrar una columna de user_id
a customer_id
no rompe las consultas, ya que el sistema la sigue rastreando mediante el ID original. Las columnas eliminadas se eliminan lógicamente pero permanecen en los archivos de datos subyacentes, lo que permite que las consultas sobre snapshots antiguos sigan siendo correctas. Las promociones de tipo — como convertir un entero en un long o un float en un double — se admiten automáticamente, aunque los cambios incompatibles (por ejemplo, entero → string) deben realizarse con precaución y se rechazan si no son seguros.
Este seguimiento basado en IDs es lo que hace que la evolución del esquema en Iceberg sea verdaderamente segura y predecible. Se puede evolucionar una tabla durante meses o años, añadiendo nuevos campos, renombrando columnas o eliminando las que ya no se usan, sin preocuparse por romper consultas históricas o corromper pipelines analíticos.
Particionado oculto
Iceberg también introduce un enfoque moderno para el particionado de datos, eliminando muchas de las limitaciones de los sistemas tradicionales basados en directorios. En formatos como Hive, el particionado se refleja directamente en la estructura de carpetas del sistema de archivos, lo que puede generar problemas de rendimiento, errores en la planificación de consultas y dificultades para evolucionar el esquema de partición.
Iceberg, en cambio, gestiona el particionado de forma interna mediante metadatos. Esto permite lo que se conoce como particionado oculto, donde los detalles del particionado no se exponen en la ruta de los archivos, sino que se almacenan en los manifiestos y listas de manifiestos. Gracias a esto, se pueden realizar cambios en la estrategia de particionado —como agregar nuevas columnas de partición o modificar las existentes— sin necesidad de reorganizar físicamente los datos ni romper compatibilidad con snapshots anteriores.
Además, este enfoque permite una evolución del particionado, lo que significa que una tabla puede tener diferentes esquemas de partición a lo largo del tiempo, y cada snapshot conserva el esquema que tenía en el momento de su creación. Esto es especialmente útil en entornos donde los patrones de acceso cambian o donde se requiere flexibilidad para optimizar el rendimiento de las consultas.
El resultado es una planificación de consultas más rápida, una mayor robustez frente a errores de diseño y una experiencia mucho más fluida para los equipos que gestionan grandes volúmenes de datos.
Conclusión
Apache Iceberg está diseñado para los data lakehouses modernos, donde la flexibilidad, la precisión y la escalabilidad son fundamentales. Su arquitectura centrada en los metadatos garantiza que las tablas sean completamente consultables y consistentes entre distintos motores, mientras que los snapshots, las ramas y las etiquetas proporcionan un historial robusto y capacidades de viaje en el tiempo. La evolución del esquema y el particionado oculto permiten añadir, renombrar o eliminar columnas, así como modificar estrategias de particionado, sin necesidad de reescribir los datos ni romper las consultas existentes.
La dependencia de un catálogo, con su puntero atómico al archivo de metadatos actual de la tabla, asegura que los commits sean completamente consistentes y con propiedades similares a ACID, incluso en entornos concurrentes con múltiples motores. Al mismo tiempo, el diseño basado en manifiestos y las estadísticas de partición permiten a los motores de consulta eliminar archivos irrelevantes de forma eficiente, soportando tablas con millones de archivos sin degradación del rendimiento.
Todas estas características se combinan para hacer de Iceberg un formato independiente del motor. Spark, Flink, Trino, Presto, Hive y otros motores pueden compartir de forma segura las mismas tablas, aprovechando los metadatos de Iceberg para interpretar correctamente los datos, aplicar cambios de esquema y respetar los snapshots. La clave de esta flexibilidad es su diseño centrado en los metadatos. Las tablas Iceberg almacenan toda la información que un motor de consulta necesita — esquema, particionado, snapshots, manifiestos y estadísticas a nivel de archivo — en archivos de metadatos bien definidos e inmutables. Los archivos de datos en sí utilizan formatos estándar como Parquet, ORC o Avro, por lo que cualquier motor que pueda leer estos formatos puede participar.
Dado que toda la información histórica está capturada en los metadatos, los motores no necesitan asumir nada sobre estructuras de directorios ni registros internos. Simplemente leen los metadatos de la tabla para determinar exactamente qué datos pertenecen a un snapshot. Incluso operaciones como el viaje en el tiempo, la ramificación o la evolución del esquema funcionan de manera consistente entre motores gracias a la estandarización del formato de metadatos.
En resumen, Iceberg ofrece un formato de tabla no solo escalable y eficiente, sino también flexible, confiable y preparado para el futuro. Permite a los equipos evolucionar sus datos, experimentar de forma segura y consultar desde distintos motores — todo mientras se mantiene la precisión, la eficiencia y la simplicidad. Para las organizaciones que están construyendo data lakehouses modernos, Iceberg representa un camino claro hacia una gestión de datos robusta y sostenible a largo plazo.
Leave a Reply