Apache Iceberg est rapidement devenu un standard pour les formats de tables ouverts dans l'écosystème big data, offrant des transactions ACID, l'évolution du schéma et la capacité de voyage dans le temps. Cependant, comme pour toute solution de data lake à grande échelle, l'efficacité des coûts est une préoccupation majeure pour les équipes d'ingénierie. Les deux opérations les plus critiques pour contrôler les coûts et les performances dans Iceberg sont la compaction des fichiers et l'expiration des instantanés. Une mauvaise gestion de ces processus peut entraîner des factures de stockage excessives et une dégradation des performances des requêtes.
Comprendre la compaction des fichiers
Avec le temps, les écritures fréquentes et de petite taille dans une table Iceberg entraînent un ensemble fragmenté de petits fichiers. Bien que les petits fichiers soient excellents pour le parallélisme lors de l'ingestion, ils sont désastreux pour l'analyse. Le balayage de milliers de minuscules fichiers entraîne des coûts élevés d'appels API sur les magasins d'objets comme S3 ou GCS et ralentit les moteurs de requêtes comme Spark et Trino. La compaction des fichiers (ou « bin-packing ») fusionne ces petits fichiers en fichiers de taille optimale plus grands (généralement de 128 Mo à 256 Mo).
Une compaction régulière garantit que vos données sont stockées dans un format efficace à la fois pour le stockage et la récupération. Vous pouvez planifier cela comme un travail de maintenance ou le déclencher de manière programmatique.
// Exemple : Compaction en utilisant Spark Iceberg
import org.apache.iceberg.spark.SparkCatalog
import org.apache.spark.sql.SparkSession
val spark = SparkSession.builder()
.appName("Iceberg Compaction")
.config("spark.sql.catalog.demo", "org.apache.iceberg.spark.SparkCatalog")
.config("spark.sql.catalog.demo.type", "hadoop")
.config("spark.sql.catalog.demo.warehouse", "s3://my-bucket/iceberg/warehouse")
.getOrCreate()
// Réécrire les petits fichiers en fichiers plus grands
spark.sql("REWRITE FILES TABLE demo.my_table")
// Optionnellement, spécifier une taille de fichier cible
spark.sql("REWRITE FILES TABLE demo.my_table OPTIONS('target-file-size-bytes' 134217728)")
Gérer l'expiration des instantanés
Iceberg prend en charge le voyage dans le temps, ce qui signifie qu'il conserve l'historique de votre table via des instantanés. Chaque instantané référence un ensemble de fichiers. Si vous supprimez des données ou réécrivez des fichiers sans nettoyer les anciens instantanés, les anciens fichiers de données restent sur le disque car les instantanés les référencent toujours. Ces « données zombies » consomment de l'espace de stockage pour lequel vous payez toujours.
L'expiration des instantanés supprime les anciens instantanés et, surtout, supprime les fichiers de données qui ne sont plus référencés par aucun instantané restant. C'est essentiel pour le contrôle des coûts. Cependant, vous devez équilibrer la période de rétention avec vos besoins commerciaux en matière d'audit ou de capacités de retour arrière.
// Exemple : Expire les instantanés ayant plus de 7 jours
import org.apache.iceberg.Table
val table = spark.catalog.table("demo.my_table")
// Expire les instantanés ayant plus de 7 jours
table.expireSnapshots()
.retainLast(3) // Conserver les 3 derniers instantanés quel que soit leur âge
.olderThan(System.currentTimeMillis() - (7L * 24L * 60L * 60L * 1000L))
.commit()
Meilleures pratiques pour l'optimisation des coûts
- Planifier une maintenance régulière : Utilisez un planificateur comme Airflow, Dagster ou cron pour exécuter les travaux de compaction et d'expiration quotidiennement ou hebdomadairement.
- Surveiller les nombres de fichiers : Alertez si le nombre de fichiers dans une table dépasse un seuil, indiquant la nécessité d'une compaction immédiate.
- Tester les politiques d'expiration : Simulez l'expiration des instantanés dans un environnement de préproduction pour vous assurer de ne pas supprimer de données nécessaires à la conformité ou au retour arrière.
- Utiliser ORC ou Parquet : Choisissez des formats colonnaires avec des ratios de compression élevés pour réduire encore les coûts de stockage.
Conclusion
L'optimisation d'Apache Iceberg pour un stockage cloud rentable nécessite une approche proactive de la gestion du cycle de vie des données. En compactant régulièrement les petits fichiers et en expirant les anciens instantanés, vous pouvez réduire considérablement les coûts de stockage et améliorer les performances des requêtes. La mise en œuvre de travaux de maintenance automatisés n'est pas optionnelle ; c'est une meilleure pratique pour tout déploiement Iceberg de niveau production. Commencez petit, surveillez vos métriques et ajustez vos politiques pour qu'elles correspondent à vos exigences de charge de travail spécifiques.