Apache Iceberg: Un Formato de Tabla Abierto para un Paisaje de Big Data Moderno
1. Introducción
Este tutorial discutirá Apache Iceberg, un popular formato de tabla abierto en el paisaje de big data actual. Exploraremos la arquitectura de Iceberg y algunas de sus características importantes a través de un ejemplo práctico con distribuciones de código abierto.
2. Origen de Apache Iceberg
Iceberg fue iniciado en Netflix por Ryan Blue y Dan Weeks alrededor de 2017. Surgió principalmente debido a las limitaciones del formato de tabla de Hive. Uno de los problemas críticos con Hive era su incapacidad para garantizar la corrección en ausencia de transacciones atómicas estables.
Los objetivos de diseño de Iceberg eran abordar estos problemas y proporcionar tres mejoras clave:
- Soporte a transacciones ACID y garantizar la corrección de los datos.
- Mejorar el rendimiento permitiendo operaciones de grano fino a nivel de archivos.
- Simplificar y ofuscar el mantenimiento de tablas.
Iceberg fue más tarde de código abierto y contribuido a la Fundación Apache, donde se convirtió en un proyecto de nivel superior en 2020. Como resultado, Apache Iceberg se ha convertido en el estándar abierto más popular para formatos de tablas. Casi todos los grandes actores del paisaje de big data hoy en día soportan tablas Iceberg.
3. Arquitectura de Apache Iceberg
Una de las decisiones clave de la arquitectura de Iceberg fue rastrear la lista completa de archivos de datos dentro de una tabla en lugar de directorios. Este enfoque tiene muchas ventajas, como un mejor rendimiento de consulta.
Dentro de la arquitectura de Iceberg hay tres capas:
3.1. Capa de Catálogo
La capa de catálogo tiene varias funciones, pero lo más importante, almacena la ubicación del puntero de metadata actual. Cualquier motor de computación que desee operar en tablas Iceberg debe acceder al catálogo y obtener este puntero de metadata actual.
El catálogo también soporta operaciones atómicas mientras se actualiza el puntero de metadata actual. Esto es esencial para permitir transacciones atómicas en tablas Iceberg. Las características disponibles dependen del catálogo que utilicemos. Por ejemplo, Nessie proporciona un control de versiones de datos inspirado en Git.
3.2. Capa de Metadata
La capa de metadata contiene la jerarquía de archivos. El archivo en la parte superior es un archivo de metadata que almacena metadata acerca de una tabla Iceberg. Rastreando el esquema de la tabla, la configuración de partición, propiedades personalizadas, snapshots, y también cuál snapshot es el actual.
El archivo de metadata apunta a una lista de manifiestos, que almacena metadata sobre cada archivo de manifiesto que compone un snapshot, incluyendo información como la ubicación del archivo de manifiesto y a qué snapshot se agregó.
Finalmente, el archivo de manifiesto rastrea archivos de datos y proporciona detalles adicionales. Los archivos de manifiesto permiten a Iceberg rastrear datos a nivel de archivo y contienen información útil que mejora la eficiencia y el rendimiento de las operaciones de lectura.
3.3. Capa de Datos
La capa de datos es donde residen los archivos de datos, probablemente en un servicio de almacenamiento de objetos en la nube como AWS S3. Iceberg admite varios formatos de archivo, como Apache Parquet, Apache Avro, y Apache ORC.
Parquet es el formato de archivo predeterminado para almacenar datos en Iceberg. Su beneficio clave es el almacenamiento eficiente. Además, cuenta con esquemas de compresión y codificación de alto rendimiento. También admite un acceso eficiente a los datos, especialmente para consultas que se dirigen a columnas específicas de una tabla amplia.
4. Características Importantes de Apache Iceberg
Apache Iceberg ofrece consistencia transaccional, permitiendo que múltiples aplicaciones trabajen juntas sobre los mismos datos. También tiene características como snapshots, evolución de esquema completo y particionamiento oculto.
4.1. Snapshots
La metadata de la tabla Iceberg mantiene un registro de snapshots que representa los cambios aplicados a una tabla. Por lo tanto, un snapshot representa el estado de la tabla en algún momento. Iceberg admite aislamiento de lectores y consultas de viaje en el tiempo basadas en snapshots.
Para la gestión del ciclo de vida de snapshots, Iceberg también admite ramas y etiquetas, que son referencias nombradas a snapshots:
4.2. Particionamiento
Iceberg particiona los datos agrupando filas similares al escribir. Por ejemplo, puede particionar eventos de registro por fecha y agruparlos en archivos con la misma fecha de evento. De este modo, puede omitir archivos de otras fechas que no tienen datos útiles y hacer que las consultas sean más rápidas.
Curiosamente, Iceberg admite el particionamiento oculto. Eso significa que maneja la tediosa y propensa a errores tarea de producir valores de partición para filas en una tabla. Los usuarios no necesitan saber cómo se particiona la tabla, y las distribuciones de partición pueden evolucionar según sea necesario. Esta es una diferencia fundamental del particionamiento admitido por formatos de tabla anteriores como Hive. Con Hive, debemos proporcionar los valores de partición. Esto vincula nuestras consultas de trabajo al esquema de particionamiento de la tabla, por lo que no puede cambiar sin romper consultas.
4.3. Evolución
Iceberg admite la evolución de la tabla de manera fluida y se refiere a esto como “evolución de tabla en su lugar”. Por ejemplo, podemos cambiar el esquema de la tabla, incluso en una estructura anidada. Además, la configuración de partición también puede cambiar en respuesta a cambios en el volumen de datos.
Para apoyar esto, Iceberg no requiere reescribir los datos de la tabla o migrar a una nueva tabla. Detrás de escena, Iceberg realiza la evolución del esquema simplemente realizando cambios en la metadata. Por lo tanto, no se reescriben archivos de datos para realizar la actualización.
5. Manos a la obra con Apache Iceberg
Apache Iceberg ha sido diseñado como un estándar comunitario abierto. Es una opción popular en arquitecturas de datos modernas y es interoperable con muchas herramientas de datos.
En esta sección, veremos a Apache Iceberg en acción, implementando un catálogo REST de Iceberg sobre un almacenamiento de Minio con Trino como el motor de consulta.
5.1. Instalación
Utilizaremos imágenes de Docker para desplegar y conectar Minio, el catálogo REST de Iceberg y Trino. Es preferible tener una solución como Docker Desktop o Podman para completar estas instalaciones.
Empecemos creando una red dentro de Docker:
docker network create data-network
Los comandos en este tutorial están destinados para una máquina Windows. Se pueden requerir cambios para otros sistemas operativos.
Ahora deployaremos Minio con almacenamiento persistente (montar el directorio del host “data” como volumen):
docker run --name minio --net data-network -p 9000:9000 -p 9001:9001 \
--volume .\data:/data quay.io/minio/minio:RELEASE.2024-09-13T20-26-02Z.fips \
server /data --console-address ":9001"
Como siguiente paso, deployaremos el catálogo REST de Iceberg. Esta es una imagen contribuida por un Tabular que expone una implementación del catálogo REST de Iceberg respaldado por una implementación de catálogo existente:
docker run --name iceberg-rest --net data-network -p 8181:8181 \
--env-file ./env.list \
tabulario/iceberg-rest:1.6.0
Aquí, estamos proporcionando variables de entorno como un archivo que contiene todas las configuraciones necesarias para que el catálogo REST de Iceberg funcione con Minio:
CATALOG_WAREHOUSE=s3://warehouse/
CATALOG_IO__IMPL=org.apache.iceberg.aws.s3.S3FileIO
CATALOG_S3_ENDPOINT=http://minio:9000
CATALOG_S3_PATH-STYLE-ACCESS=true
AWS_ACCESS_KEY_ID=minioadmin
AWS_SECRET_ACCESS_KEY=minioadmin
AWS_REGION=us-east-1
Ahora, deployaremos Trino para trabajar con el catálogo REST de Iceberg. Podemos configurar Trino para usar el catálogo REST y Minio que implementamos anteriormente proporcionando un archivo de propiedades como montaje de volumen:
docker run --name trino --net data-network -p 8080:8080 \
--volume .\catalog:/etc/trino/catalog \
--env-file ./env.list \
trinodb/trino:449
El archivo de propiedades contiene los detalles del catálogo REST y Minio:
connector.name=iceberg
iceberg.catalog.type=rest
iceberg.rest-catalog.uri=http://iceberg-rest:8181/
iceberg.rest-catalog.warehouse=s3://warehouse/
iceberg.file-format=PARQUET
hive.s3.endpoint=http://minio:9000
hive.s3.path-style-access=true
Como antes, también alimentamos las credenciales de acceso de Minio como variables de entorno:
AWS_ACCESS_KEY_ID=minioadmin
AWS_SECRET_ACCESS_KEY=minioadmin
AWS_REGION=us-east-1
La propiedad *hive.s3.path-style-access* es requerida para Minio y no es necesaria si utilizamos AWS S3.
5.2. Operaciones de Datos
Podemos usar Trino para realizar diferentes operaciones en el catálogo REST. Trino viene con un CLI incorporado para facilitarnos esto. Primero, accedamos al CLI desde dentro del contenedor de Docker:
docker exec -it trino trino
Esto debería proporcionarnos un prompt tipo shell para enviar nuestras consultas SQL. Como hemos visto anteriormente, un cliente para Iceberg necesita comenzar accediendo al catálogo primero. Veamos si tenemos catálogos predeterminados disponibles:
trino> SHOW catalogs;
Usaremos *iceberg*. Comencemos creando un esquema en Trino (que se traduce en un espacio de nombres en Iceberg):
trino> CREATE SCHEMA iceberg.demo;
Ahora, podemos crear una tabla dentro de este esquema:
trino> CREATE TABLE iceberg.demo.customer (
-> id INT,
-> first_name VARCHAR,
-> last_name VARCHAR,
-> age INT);
Vamos a insertar algunas filas:
trino> INSERT INTO iceberg.demo.customer (id, first_name, last_name, age) VALUES
-> (1, 'John', 'Doe', 24),
-> (2, 'Jane', 'Brown', 28),
-> (3, 'Alice', 'Johnson', 32),
-> (4, 'Bob', 'Williams', 26),
-> (5, 'Charlie', 'Smith', 35);
Podemos consultar la tabla para obtener los datos insertados:
trino> SELECT * FROM iceberg.demo.customer;
Como podemos ver, podemos usar la sintaxis SQL familiar para trabajar con un formato de tabla altamente escalable y abierto para volúmenes masivos de datos.
5.3. Un Vistazo a los Archivos
Veamos qué tipo de archivos se generan en nuestro almacenamiento.
Minio proporciona un consolidador que podemos acceder en http://localhost:9001. Encontramos dos directorios bajo warehouse/demo:
- data
- metadata
Primero, veamos el directorio de metadata:
Contiene los archivos de metadata (*metadata.json*), listas de manifiestos (*snap-*.avro*), y archivos de manifiesto (*avro*, *stats*). El archivo *stats* contiene información sobre los datos de la tabla utilizada para mejorar el rendimiento de las consultas.
Ahora, veamos qué hay en el directorio data:
Contiene un archivo de datos en formato Parquet que contiene los datos reales que creamos a través de nuestras consultas.
6. Conclusión
Apache Iceberg se ha convertido en una opción popular para implementar “data lakehouses” hoy en día. Ofrece características como snapshots, particionamiento oculto y evolución de tablas en su lugar. Junto con la especificación del catálogo REST, se está convirtiendo rápidamente en el estándar de facto para formatos de tabla abiertos.
En resumen, Apache Iceberg no solo mejora la integridad y el rendimiento del manejo de datos, sino que también proporciona un marco flexible y escalable que puede ayudar a los programadores y profesionales de datos a optimizar sus flujos de trabajo y a manejar grandes volúmenes de información de manera más efectiva. La integración de estas características en arquitecturas modernas es esencial para mantener la competitividad en un entorno de datos que está en constante evolución.