Garde-fou anti-explosion : estimer une jointure avant de la payer
Le nombre de lignes produites par une jointure se calcule à l'avance : somme des produits des cardinalités par clé. Un seuil transforme l'estimation en garde-fou bloquant.
Cas d'usage
Empêcher un job de générer 40 milliards de lignes parce qu'une clé censée être unique ne l'est plus.
Prérequis
PySpark 3.x
Python
from pyspark.sql import functions as F
g = commandes.groupBy("ref").agg(F.count("*").alias("n_gauche"))
d = tarifs.groupBy("ref").agg(F.count("*").alias("n_droite"))
croise = g.join(d, "ref").withColumn(
"produit", F.col("n_gauche") * F.col("n_droite"))
estimation = croise.agg(F.sum("produit")).first()[0]
print(f"Jointure estimée : {estimation:,} lignes")
if estimation > 500_000_000:
croise.orderBy(F.desc("produit")).show(3)
raise RuntimeError("Explosion probable : cle 'ref' non unique des deux cotes")Résultat
Jointure estimée : 38,412,907,224 lignes +--------+--------+--------+--------------+ | ref|n_gauche|n_droite| produit| +--------+--------+--------+--------------+ |REF-MISC| 184,302| 208,114|38,355,826,428| |REF-0042| 1,204| 12| 14,448| |REF-1183| 880| 8| 7,040| +--------+--------+--------+--------------+ RuntimeError: Explosion probable : cle 'ref' non unique des deux cotes → REF-MISC est un fourre-tout présent 184 k × 208 k fois : 38 Md de lignes évitées
PySparkJointureCartésienGarde-fou