Saltar al contenido principal
Recomendamos usar la función de tabla de Iceberg para trabajar con datos de Iceberg en ClickHouse. Actualmente, la función de tabla de Iceberg ofrece funcionalidad suficiente y una interfaz parcial de solo lectura para tablas Iceberg.El motor de tabla Iceberg está disponible, pero puede tener limitaciones. ClickHouse no se diseñó originalmente para admitir tablas con esquemas que cambian externamente, lo que puede afectar la funcionalidad del motor de tabla Iceberg. Como resultado, algunas funciones que sí funcionan con tablas normales pueden no estar disponibles o no funcionar correctamente, especialmente al usar el analizador antiguo.Para obtener una compatibilidad óptima, sugerimos usar la función de tabla de Iceberg mientras seguimos mejorando la compatibilidad con el motor de tabla Iceberg.
Este motor proporciona una integración de solo lectura con tablas Apache Iceberg existentes en Amazon S3, Azure, HDFS y tablas almacenadas localmente.

Crear tabla

Ten en cuenta que la tabla Iceberg ya debe existir en el almacenamiento; este comando no admite parámetros DDL para crear una tabla nueva.
CREATE TABLE iceberg_table_s3
    ENGINE = IcebergS3(url,  [, NOSIGN | access_key_id, secret_access_key, [session_token]], format, [,compression], [,extra_credentials])

CREATE TABLE iceberg_table_azure
    ENGINE = IcebergAzure(connection_string|storage_account_url, container_name, blobpath, [account_name, account_key, format, compression])

CREATE TABLE iceberg_table_hdfs
    ENGINE = IcebergHDFS(path_to_table, [,format] [,compression_method])

CREATE TABLE iceberg_table_local
    ENGINE = IcebergLocal(path_to_table, [,format] [,compression_method])

Argumentos del motor

La descripción de estos argumentos coincide con la de los argumentos de los motores S3, AzureBlobStorage, HDFS y File, respectivamente. format indica el formato de los archivos de datos de la tabla Iceberg. Para IcebergS3, se puede usar el parámetro opcional extra_credentials para pasar un role_arn para acceso basado en roles en ClickHouse Cloud. Consulta Secure S3 para ver los pasos de configuración. Los parámetros del motor pueden especificarse mediante colecciones con nombre

Ejemplo

CREATE TABLE iceberg_table ENGINE=IcebergS3('http://test.s3.amazonaws.com/clickhouse-bucket/test_table', 'test', 'test')
Uso de colecciones con nombre:
<clickhouse>
    <named_collections>
        <iceberg_conf>
            <url>http://test.s3.amazonaws.com/clickhouse-bucket/</url>
            <access_key_id>test</access_key_id>
            <secret_access_key>test</secret_access_key>
        </iceberg_conf>
    </named_collections>
</clickhouse>
CREATE TABLE iceberg_table ENGINE=IcebergS3(iceberg_conf, filename = 'test_table')

Alias

El motor de tabla Iceberg ahora es un alias de IcebergS3.

Tipos de datos

La siguiente tabla muestra cómo se asignan los tipos de datos de Iceberg a los tipos de datos de ClickHouse durante la inferencia del esquema (para su lectura).

Tipos primitivos

Tipo de IcebergTipo de ClickHouseNotas
booleanBool
intInt32
long, bigintInt64
floatFloat32
doubleFloat64
dateDate32
timeInt64Microsegundos desde la medianoche
timestampDateTime64(6)Microsegundos, sin zona horaria
timestamptzDateTime64(6, 'UTC')Microsegundos, zona horaria UTC
timestamp_nsDateTime64(9)Nanosegundos, sin zona horaria (solo a partir de Iceberg v3)
timestamptz_nsDateTime64(9, 'UTC')Nanosegundos, zona horaria UTC (solo a partir de Iceberg v3)
string, binaryString
uuidUUID
fixed(N)FixedString(N)
decimal(P, S)Decimal(P, S)

Tipos complejos

Tipo de IcebergTipo de ClickHouse
listArray
mapMap
structTuple

Evolución del esquema

ClickHouse admite leer tablas Iceberg cuyo esquema ha evolucionado con el tiempo. Esto incluye tablas en las que se han agregado, eliminado o reordenado columnas, así como columnas que han pasado de obligatorias a Nullable. Además, se admiten las siguientes conversiones de tipos:
  • int -> long
  • float -> double
  • decimal(P, S) -> decimal(P’, S) donde P’ > P.
Actualmente, no es posible cambiar estructuras anidadas ni los tipos de los elementos dentro de arrays y maps. Para leer una tabla cuyo esquema haya cambiado después de su creación con inferencia dinámica de esquema, establezca allow_dynamic_metadata_for_data_lakes = true al crear la tabla.

Poda de particiones

ClickHouse admite la poda de particiones en las consultas SELECT sobre tablas Iceberg, lo que ayuda a optimizar el rendimiento de las consultas al omitir archivos de datos irrelevantes. Para habilitar la poda de particiones, establezca use_iceberg_partition_pruning = 1. Para obtener más información sobre la poda de particiones de Iceberg, consulte https://iceberg.apache.org/spec/#partitioning

Viaje en el tiempo

ClickHouse admite el viaje en el tiempo en tablas Iceberg, lo que permite consultar datos históricos con una marca temporal específica o un ID de instantánea.

Procesamiento de tablas con filas eliminadas

ClickHouse admite la lectura de tablas Iceberg que utilizan los siguientes métodos de eliminación: El siguiente método de eliminación no es compatible:

Uso básico

 SELECT * FROM example_table ORDER BY 1 
 SETTINGS iceberg_timestamp_ms = 1714636800000
 SELECT * FROM example_table ORDER BY 1 
 SETTINGS iceberg_snapshot_id = 3547395809148285433
Nota: No puede especificar a la vez los parámetros iceberg_timestamp_ms e iceberg_snapshot_id en la misma consulta.

Consideraciones importantes

  • Normalmente, las instantáneas se crean cuando:
    • Se escriben datos nuevos en la tabla
    • Se realiza algún tipo de compactación de datos
  • Los cambios de esquema normalmente no crean instantáneas - Esto da lugar a comportamientos importantes al usar viaje en el tiempo con tablas que han pasado por una evolución del esquema.

Escenarios de ejemplo

Todos los escenarios están escritos en Spark porque CH todavía no admite la escritura en tablas Iceberg.

Escenario 1: Cambios de esquema sin nuevas instantáneas

Considere la siguiente secuencia de operaciones:
 -- Crear una tabla con dos columnas
  CREATE TABLE IF NOT EXISTS spark_catalog.db.time_travel_example (
  order_number int, 
  product_code string
  ) 
  USING iceberg 
  OPTIONS ('format-version'='2')

-- Insertar datos en la tabla
  INSERT INTO spark_catalog.db.time_travel_example VALUES 
    (1, 'Mars')

  ts1 = now() // Un fragmento de pseudocódigo

-- Modificar la tabla para agregar una nueva columna
  ALTER TABLE spark_catalog.db.time_travel_example ADD COLUMN (price double)
 
  ts2 = now()

-- Insertar datos en la tabla
  INSERT INTO spark_catalog.db.time_travel_example VALUES (2, 'Venus', 100)

   ts3 = now()

-- Consultar la tabla en cada timestamp
  SELECT * FROM spark_catalog.db.time_travel_example TIMESTAMP AS OF ts1;

+------------+------------+
|order_number|product_code|
+------------+------------+
|           1|        Mars|
+------------+------------+
  SELECT * FROM spark_catalog.db.time_travel_example TIMESTAMP AS OF ts2;

+------------+------------+
|order_number|product_code|
+------------+------------+
|           1|        Mars|
+------------+------------+

  SELECT * FROM spark_catalog.db.time_travel_example TIMESTAMP AS OF ts3;

+------------+------------+-----+
|order_number|product_code|price|
+------------+------------+-----+
|           1|        Mars| NULL|
|           2|       Venus|100.0|
+------------+------------+-----+
Resultados de la consulta en distintas marcas de tiempo:
  • En ts1 & ts2: Solo aparecen las dos columnas originales
  • En ts3: Aparecen las tres columnas, con NULL en el precio de la primera fila

Escenario 2: Diferencias entre el esquema histórico y el actual

Una consulta de viaje en el tiempo en el momento actual puede mostrar un esquema distinto del de la tabla actual:
-- Crear una tabla
  CREATE TABLE IF NOT EXISTS spark_catalog.db.time_travel_example_2 (
  order_number int, 
  product_code string
  ) 
  USING iceberg 
  OPTIONS ('format-version'='2')

-- Insertar datos iniciales en la tabla
</OLD_STRING>
<OLD_STRING>
-- Alter table to add a new column
</OLD_STRING>
<NEW_STRING>
-- Modificar la tabla para añadir una nueva columna
  INSERT INTO spark_catalog.db.time_travel_example_2 VALUES (2, 'Venus');

-- Alter table to add a new column
  ALTER TABLE spark_catalog.db.time_travel_example_2 ADD COLUMN (price double);

  ts = now();

-- Consultar la tabla en el momento actual pero usando la sintaxis de timestamp

  SELECT * FROM spark_catalog.db.time_travel_example_2 TIMESTAMP AS OF ts;

    +------------+------------+
    |order_number|product_code|
    +------------+------------+
    |           2|       Venus|
    +------------+------------+

-- Consultar la tabla en el momento actual
  SELECT * FROM spark_catalog.db.time_travel_example_2;
    +------------+------------+-----+
    |order_number|product_code|price|
    +------------+------------+-----+
    |           2|       Venus| NULL|
    +------------+------------+-----+
Esto sucede porque ALTER TABLE no crea una nueva instantánea, sino que, para la tabla actual, Spark toma el valor de schema_id del archivo de metadatos más reciente, no de una instantánea.

Escenario 3: Diferencias entre el esquema histórico y el actual

La segunda es que, al usar viaje en el tiempo, no puedes obtener el estado de la tabla antes de que se haya escrito ningún dato en ella:
-- Crear una tabla
  CREATE TABLE IF NOT EXISTS spark_catalog.db.time_travel_example_3 (
  order_number int, 
  product_code string
  ) 
  USING iceberg 
  OPTIONS ('format-version'='2');

  ts = now();

-- Consultar la tabla en un timestamp específico
  SELECT * FROM spark_catalog.db.time_travel_example_3 TIMESTAMP AS OF ts; -- Finaliza con error: Cannot find a snapshot older than ts.
En ClickHouse, el comportamiento coincide con el de Spark. Puedes sustituir mentalmente las consultas Select de Spark por las de ClickHouse y funcionará igual.

Resolución del archivo de metadatos

Al usar el table engine Iceberg en ClickHouse, el sistema necesita localizar el archivo metadata.json correcto que describe la estructura de la tabla Iceberg. Así funciona este proceso de resolución:
  1. Especificación directa de la ruta:
  • Si estableces iceberg_metadata_file_path, el sistema usará esta ruta exacta combinándola con la ruta del directorio de la tabla Iceberg.
  • Cuando se proporciona este ajuste, se ignoran todos los demás ajustes de resolución.
  1. Coincidencia del UUID de la tabla:
  • Si se especifica iceberg_metadata_table_uuid, el sistema:
    • Solo examinará los archivos .metadata.json del directorio metadata
    • Filtrará los archivos que contengan un campo table-uuid que coincida con el UUID especificado (sin distinguir entre mayúsculas y minúsculas)
  1. Búsqueda predeterminada:
  • Si no se proporciona ninguno de los ajustes anteriores, todos los archivos .metadata.json del directorio metadata pasan a ser candidatos

Selección del archivo más reciente

Después de identificar los archivos candidatos según las reglas anteriores, el sistema determina cuál es el más reciente:
  • Si iceberg_recent_metadata_file_by_last_updated_ms_field está habilitado:
    • Se selecciona el archivo con el valor last-updated-ms más alto
  • En caso contrario:
    • Se selecciona el archivo con el número de versión más alto
    • (La versión aparece como V en nombres de archivo con el formato V.metadata.json o V-uuid.metadata.json)
Nota: Todos los ajustes mencionados (salvo que se especifique explícitamente lo contrario) son ajustes a nivel de motor y deben especificarse durante la creación de la tabla, como se muestra a continuación:
CREATE TABLE example_table ENGINE = Iceberg(
    's3://bucket/path/to/iceberg_table'
) SETTINGS iceberg_metadata_table_uuid = '6f6f6407-c6a5-465f-a808-ea8900e35a38';
Nota: Aunque los catálogos Iceberg normalmente se encargan de la resolución de metadatos, el motor de tabla Iceberg de ClickHouse interpreta directamente los archivos almacenados en S3 como tablas Iceberg, por lo que es importante comprender estas reglas de resolución.

Caché de datos

El motor de tabla y la función de tabla Iceberg admiten el caché de datos, al igual que los almacenamientos S3, AzureBlobStorage y HDFS. Consulte aquí.

Caché de metadatos

El motor de tabla y la función de tabla Iceberg admiten una caché de metadatos que almacena información de los archivos de manifiesto, la lista de manifiestos y el JSON de metadatos. La caché reside en memoria. Esta funcionalidad se controla mediante la configuración use_iceberg_metadata_files_cache, habilitada de forma predeterminada.

Precarga asíncrona de metadatos

La precarga asíncrona de metadatos puede habilitarse al crear una tabla Iceberg configurando iceberg_metadata_async_prefetch_period_ms. Si se establece en 0 (valor predeterminado) o si la caché de metadatos no está habilitada, la precarga asíncrona se desactiva. Para habilitar esta función, debe proporcionarse un valor distinto de cero en milisegundos. Este valor representa el intervalo entre los ciclos de precarga. Si está habilitada, el servidor ejecutará una operación recurrente en segundo plano para listar el catálogo remoto y detectar una nueva versión de los metadatos. A continuación, los analizará y recorrerá recursivamente la instantánea, obteniendo los archivos activos de lista de manifiestos y los archivos de manifiesto. Los archivos que ya estén disponibles en la caché de metadatos no se volverán a descargar. Al final de cada ciclo de precarga, la instantánea de metadatos más reciente estará disponible en la caché de metadatos.
CREATE TABLE example_table ENGINE = Iceberg(
    's3://bucket/path/to/iceberg_table'
) SETTINGS
    iceberg_metadata_async_prefetch_period_ms = 60000;
Para aprovechar al máximo la precarga asíncrona de metadatos durante las operaciones de lectura, el parámetro iceberg_metadata_staleness_ms debe especificarse como parámetro de consulta o de sesión. De forma predeterminada (0, no especificado), en el contexto de cada consulta, el servidor obtendrá los metadatos más recientes del catálogo remoto. Al especificar una tolerancia a la desactualización de los metadatos, se permite que el servidor use la versión en caché de la instantánea de metadatos sin consultar el catálogo remoto. Si hay una versión de metadatos en caché y se descargó dentro de la ventana de desactualización indicada, se usará para procesar la consulta. De lo contrario, se obtendrá la versión más reciente del catálogo remoto.
SELECT count() FROM icebench_table WHERE ...
SETTINGS iceberg_metadata_staleness_ms=120000
Nota: La precarga asíncrona de metadatos se ejecuta en ICEBERG_SCEDULE_POOL, que es el threadpool del servidor para operaciones en segundo plano en tablas Iceberg activas. El tamaño de este threadpool se controla mediante el parámetro de configuración del servidor iceberg_background_schedule_pool_size (el valor predeterminado es 10). Nota: Actualmente se espera que el tamaño de la caché de metadatos sea suficiente para alojar por completo la instantánea de metadatos más reciente de todas las tablas activas, si la precarga asíncrona está habilitada.

Véase también

Última modificación el 10 de junio de 2026