Optimización de Tablas Iceberg: Ordenación, Estadísticas y Vectores de Eliminación
Ordenar los datos al escribir en tablas Iceberg permite que los motores de ejecución omitan archivos innecesarios basándose en estadísticas de mínimo/máximo en los archivos de manifiesto. Sin ordenación, los rangos de valores en los archivos se superponen, lo que lleva a leer todos los datos incluso con filtros estrictos.
Ejemplo de creación de una tabla y escritura sin ordenación:
spark.sql("""
CREATE TABLE habr.paper.write_ordered (
id INT,
name STRING,
event STRING
)
USING ICEBERG
""")
data = [(i, f"name_{i}", f"event_{i}") for i in range(1, 1000000)]
df = spark.createDataFrame(data, ["id", "name", "event"]).repartition(16)
df.writeTo("habr.paper.write_ordered").append()
Consultar los metadatos muestra rangos caóticos:
| id_min | id_max | file_path |
|--------|--------|-----------|
| 2 | 999994 | ... |
| 43 | 999988 | ... |
Un filtro con id < 100000 leerá todos los archivos.
Habilitar la ordenación:
spark.sql("""
ALTER TABLE habr.paper.write_ordered
WRITE ORDERED BY id
""")
Reescribir produce rangos secuenciales:
| id_min | id_max | file_path |
|--------|--------|-----------|
| 1 | 196479 | ... |
| 196480 | 395983 | ... |
Ahora, un filtro con id < 196470 lee solo un archivo.
Configuración de la Recopilación de Estadísticas de Columnas
Iceberg por defecto recopila estadísticas completas de mínimo/máximo/truncadas para todas las columnas, aumentando el tiempo de escritura sin beneficiar las consultas. En tablas típicas, el filtrado ocurre en 1-2 columnas, haciendo innecesarias las estadísticas para las demás.
Ejemplo de una tabla plana con 10 columnas:
spark.sql("""
CREATE TABLE habr.paper.typical_flat_table (
id INT,
name STRING,
col_1 STRING,
col_2 STRING,
col_3 STRING,
col_4 STRING,
col_5 STRING,
col_6 STRING,
col_7 STRING,
col_8 STRING
)
USING ICEBERG
""")
Configuración mediante TBLPROPERTIES:
spark.sql("""
ALTER TABLE habr.paper.typical_flat_table SET TBLPROPERTIES (
'write.metadata.metrics.default' = 'counts',
'write.metadata.metrics.column.id' = 'full',
'write.metadata.metrics.column.col_1' = 'none'
)
""")
- default: 'counts' — solo recuentos de filas para todas las columnas
- full: mínimo/máximo + truncadas para filtros críticos (id)
- none: deshabilitado para columnas no utilizadas
Esto reduce la sobrecarga de escritura y el volumen de metadatos sin perder la omisión de datos en campos clave.
Eliminación Vectorizada en MoR
En la estrategia Merge-on-Read, el rendimiento de lectura depende del mecanismo de aplicación de eliminaciones. Los archivos de eliminación clásicos requieren uniones con los datos.
Tipos de archivos de eliminación:
- Eliminación por igualdad: reglas de eliminación (obsoletas en v3)
- Eliminación por posición: posiciones de filas en archivos
Con Iceberg v3, la eliminación por posición evolucionó a Vectores de eliminación basados en el formato Puffin. Un vector de eliminación es una máscara de mapa de bits aplicada en un ciclo a un archivo de datos.
Ejemplo de eliminación por posición:
| file_path | pos |
|-----------|-----|
| ...parquet | 873 |
| ...parquet | 230 |
En lugar de una unión: cargar mapa de bits + operación AND lógica. Esto acelera la lectura de tablas MoR en 5-10x con un alto porcentaje de eliminaciones.
Los vectores de eliminación son especialmente efectivos para:
- ETL por lotes con actualizaciones frecuentes
- Tablas con dimensiones de cambio lento
- Streaming con MoR
Conclusiones Clave
- Ordenar con WRITE ORDERED BY en columnas filtrables reduce los archivos legibles en análisis
- Configurar write.metadata.metrics.* minimiza la sobrecarga de escritura preservando la omisión de datos
- Los vectores de eliminación en Iceberg v3 reemplazan la eliminación por posición, acelerando la lectura MoR mediante mapa de bits
- Las optimizaciones funcionan sin cambiar consultas o lógica ETL
- Los efectos se acumulan: menos archivos, menos metadatos, carga reducida en almacenamiento de objetos
— Editorial Team
Aún no hay comentarios.