Que fait Construction de tables Iceberg ?
Quand l'utiliser
- Création ou maintenance de tables Apache Iceberg sur un lakehouse.
- Choix du partitionnement, ou évolution du partitionnement/schéma sans réécriture.
- Gestion des instantanés, voyage dans le temps, compactage et petits fichiers.
- Ne PAS utiliser pour du travail spécifique à Delta (utiliser
engineering-databricks-pipelines).
Workflow
- [ ] Partitionner par colonnes de filtre de requête ; utiliser les transformations de partition cachées
- [ ] Utiliser MERGE pour les upserts idempotents
- [ ] Planifier le compactage (rewrite_data_files) pour corriger les petits fichiers
- [ ] Expirer les anciens instantanés + supprimer les fichiers orphelins pour contrôler les métadonnées/le stockage
- [ ] Faire évoluer le partitionnement/le schéma par ID de champ (aucune réécriture de données)
- Partitionner sur les colonnes de filtre en utilisant des transformations de partition cachées
(
days(ts),bucket(N, id)), afin que les requêtes élaguent sans que les utilisateurs n'ajoutent de colonnes de partition dérivées. - Écritures idempotentes via
MERGE INTObasé sur la clé métier. - Compacter régulièrement — les écritures streaming/petits lots créent de nombreux petits fichiers ;
rewrite_data_filesrestaure les performances de lecture. - Maintenir les métadonnées — expirer les anciens instantanés et supprimer les fichiers orphelins, sinon l'historique des instantanés et le stockage croissent sans limite.
- Évoluer librement — Iceberg suit les colonnes/les partitions par ID, donc ajouter/supprimer/renommer et même modifier la spécification de partition ne nécessite aucune réécriture de données.
Patterns
Création avec partitionnement caché + upsert MERGE :
CREATE TABLE lake.db.orders (order_id BIGINT, customer_id BIGINT, amount DECIMAL, ordered_at TIMESTAMP)
USING iceberg PARTITIONED BY (days(ordered_at));
MERGE INTO lake.db.orders t USING staging s ON t.order_id = s.order_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;
Maintenance (procédures Spark) :
CALL lake.system.rewrite_data_files('db.orders'); -- compacte les petits fichiers
CALL lake.system.expire_snapshots('db.orders', TIMESTAMP '2026-08-01 00:00:00');
CALL lake.system.remove_orphan_files(table => 'db.orders');
Voyage dans le temps — lire un instantané antérieur pour audit ou récupération :
SELECT * FROM lake.db.orders VERSION AS OF <snapshot_id>.
Évolution du partitionnement — ALTER TABLE ... ADD PARTITION FIELD bucket(16, customer_id)
s'applique uniquement aux nouvelles données ; les anciennes données restent valides.
Pièges courants
- Absence de compactage sur les tables streaming — l'explosion des petits fichiers réduit les performances de lecture.
- Ne jamais expirer les instantanés — les métadonnées et le stockage croissent sans limite ; planifiez l'expiration dans votre période de rétention du voyage dans le temps.
- Sur-partitionnement (par exemple par heure sur un faible volume) — trop de petites partitions ; adaptez la granularité à la taille des données.
- Ajout de colonnes de partition dérivées explicites — va à l'encontre du partitionnement caché ; utilisez les transformations.
- Réécriture aveugle au lieu de MERGE — perd l'idempotence ; utilisez MERGE par clé.
- Suppression des fichiers orphelins avec une fenêtre trop courte — peut supprimer des fichiers encore nécessaires aux écritures en cours ; utilisez une limite de sécurité.