Spark

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

Snippets liés

Retour au Data Lab