Iceberg est devenu le standard ouvert pour les tables lakehouse. En entretien Expert, on évalue la maîtrise des fonctionnalités avancées : catalog REST, partition evolution, et les stratégies d écriture.
Qu est-ce qu un Iceberg Catalog ? Pourquoi est-il central dans une architecture Lakehouse ?
## Types de catalogs Iceberg
# 1. REST Catalog (standard émergent 2025)
# Serveur HTTP qui expose l API Iceberg REST
# Compatible avec tous les engines (Spark, Trino, Flink, DuckDB)
spark = SparkSession.builder \
.config('spark.sql.catalog.prod', 'org.apache.iceberg.spark.SparkCatalog') \
.config('spark.sql.catalog.prod.catalog-impl', 'org.apache.iceberg.rest.RESTCatalog') \
.config('spark.sql.catalog.prod.uri', 'https://iceberg-catalog.monentreprise.com') \
.getOrCreate()
# 2. AWS Glue Catalog (managé AWS)
.config('spark.sql.catalog.glue.catalog-impl', 'org.apache.iceberg.aws.glue.GlueCatalog')
# 3. Nessie (versioning Git-like pour le catalog)
.config('spark.sql.catalog.nessie.catalog-impl', 'org.projectnessie.iceberg.NessieCatalog')Qu est-ce que la partition evolution ? Pourquoi est-ce un avantage majeur d Iceberg sur Hive ?
from pyiceberg.catalog import load_catalog
from pyiceberg.transforms import MonthTransform, DayTransform
catalog = load_catalog('prod')
table = catalog.load_table('analytics.orders')
# Partition Evolution : changer le schéma de partition
# sans réécrire les données existantes
with table.update_spec() as update:
# Avant : partitionné par mois
# Après : partitionner par jour (pour les nouvelles partitions)
update.remove_field('order_month') # supprimer l ancienne
update.add_identity('order_date') # ajouter la nouvelle
# Les anciennes données restent dans leurs partitions par mois
# Les nouvelles données vont dans des partitions par jour
# Iceberg gère la coexistence automatiquement
# Avec Hive : impossible sans réécrire toutes les données !Comment requêtez-vous l état d une table Iceberg à un snapshot précis ?
-- Time Travel par timestamp
SELECT * FROM prod.analytics.orders
FOR SYSTEM_TIME AS OF '2025-01-15 08:00:00';
-- Time Travel par snapshot ID
SELECT * FROM prod.analytics.orders
FOR VERSION AS OF 1234567890;
-- Lister les snapshots disponibles
SELECT * FROM prod.analytics.orders.snapshots
ORDER BY committed_at DESC
LIMIT 10;
-- Comparer deux snapshots (identifier ce qui a changé)
SELECT * FROM prod.analytics.orders.changes
BETWEEN TIMESTAMP '2025-01-14 00:00:00'
AND TIMESTAMP '2025-01-15 00:00:00';
-- Rollback vers un état précédent
CALL prod.system.rollback_to_timestamp(
'analytics.orders',
TIMESTAMP '2025-01-14 12:00:00'
);Quelle est la différence entre CoW et MoR ? Quand choisissez-vous l un ou l autre ?
| Copy-on-Write (CoW) | Merge-on-Read (MoR) | |
|---|---|---|
| Écriture | Réécriture des fichiers impactés | Écriture dans des fichiers delta (positional deletes) |
| Lecture | Lecture directe, fichiers propres | Merge à la lecture (fichiers data + deletes) |
| Coût écriture | Élevé (I/O) | Faible |
| Coût lecture | Faible | Potentiellement élevé (sans compaction) |
| Idéal pour | Lectures fréquentes, écritures rares | Mises à jour fréquentes (CDC), écritures intensives |
Quelles opérations de maintenance planifiez-vous sur vos tables Iceberg ?
## Opérations de maintenance (scheduler via Airflow)
# 1. Compaction : fusionner les petits fichiers
SPARK.sql("""
CALL prod.system.rewrite_data_files(
table => 'analytics.orders',
strategy => 'sort',
sort_order => 'order_date, region',
options => map('min-input-files', '5', 'target-file-size-bytes', '134217728')
)
""")
# 2. Expirer les anciens snapshots
SPARK.sql("""
CALL prod.system.expire_snapshots(
table => 'analytics.orders',
older_than => TIMESTAMP '2024-12-01 00:00:00',
retain_last => 3
)
""")
# 3. Supprimer les fichiers orphelins
SPARK.sql("""
CALL prod.system.remove_orphan_files(
table => 'analytics.orders',
dry_run => false
)
""")Comment faites-vous cohabiter plusieurs engines sur les mêmes tables Iceberg ?
## Trino + Iceberg : SQL OLAP performant
CREATE TABLE iceberg.analytics.orders (
order_id VARCHAR,
amount DOUBLE,
order_date DATE
) WITH (
format = 'PARQUET',
partitioning = ARRAY['month(order_date)'],
sorted_by = ARRAY['order_date']
);
## DuckDB + Iceberg (v0.10+)
INSTALL iceberg; LOAD iceberg;
SELECT * FROM iceberg_scan(
's3://mon-bucket/warehouse/analytics/orders',
allow_moved_paths = true
);
## Règle de cohabitation :
# Lire depuis tous les engines
# Écrire depuis 1 seul engine à la fois (pas de concurrent writes)
# Sauf Iceberg Multi-Writer (optimistic locking)| Niveau | Maitrise | Signal GO | NO-GO |
|---|---|---|---|
| Confirmé | Tables Iceberg basiques, time travel, catalogs | A créé des tables Iceberg, utilise le time travel, comprend les catalogs | Ne sait pas la différence entre Iceberg et un simple Parquet |
| Senior | Partition evolution, CoW vs MoR, maintenance planifiée | A fait une partition evolution, choisit CoW vs MoR selon le cas, planifie la compaction | Ne sait pas ce qu est la partition evolution |
Premier entretien gratuit. Rapport GO/NO-GO sous 48h.