Côté stockage, un petit fichier n’est pas un problème Spark : c’est un objet trop léger pour le modèle économique d’un object store et d’un format à pied de fichier. Lister 400 000 clés, ouvrir 400 000 footers Parquet, payer 400 000 GET, pour 12 Go utiles : le listing et les métadonnées coûtent plus cher que les octets.
Les causes qui naissent dans le lac, pas dans l’exécuteur :
Les remèdes sont des services de table, pas un « on écrira mieux un jour » :
VACUUM, expiration des snapshots Iceberg) pour que la compaction ne laisse pas l’ancien petit à côté du nouveau gros.Que vous parlez d’objets et de listing, pas seulement de « trop de tâches ». Sur S3, LIST n’est pas gratuit, n’est pas infiniment parallèle, et un catalog qui doit statuer 200 000 fichiers au planning d’une requête SQL met le coordinateur à genoux — Trino, Athena, Spark driver, c’est le même symptôme.
La relance : « on compacte à chaque micro-lot ? » Non. On accumule puis on compacte par vague (toutes les heures, tous les 512 Mo en attente, par partition du jour). Compacter en continu sans seuil recrée de la contention et des commits trop fréquents.
Deuxième relance : « Delta OPTIMIZE suffit-il ? » Il réécrit les données. Il ne change pas le producteur. Si le stream continue de poser 2 000 fichiers à l’heure, vous compactez un tapis roulant. Il faut les deux : moins de fichiers à l’arrivée, et une compaction de rattrapage.
Mesurer le succès au nombre de fichiers sans regarder la latence d’ingestion. Une compaction trop agressive sur une table MERGE toutes les minutes bloque ou renchérit les écritures (copy-on-write). Et à l’inverse, attendre « le weekend » sur une table de faits qui sert le matin : le dashboard de 8 h lit encore les petits de la nuit.
Le diagnostic à énoncer : compter les objets par préfixe, la taille p50/p90, le temps de LIST / de planification, puis seulement le temps de scan. Si la planification dure 40 s et le scan 8 s, vous n’avez pas un problème de CPU.