Spark

Replacing a Python UDF with native functions

A Python UDF serializes every row to a Python worker and blinds Catalyst; the same logic in native functions stays optimizable and runs 10 to 100x faster.

Prerequisites

PySpark 3.x

Python
from pyspark.sql import functions as F

# AVANT : UDF ligne à ligne, opaque pour l'optimiseur
# @udf("string")
# def clean_phone(p):
#     return re.sub(r"[^0-9+]", "", p or "")[:15]

# APRÈS : équivalent 100 % natif, vectorisé côté JVM
df_clean = df.withColumn(
    "phone_clean",
    F.substring(
        F.regexp_replace(F.coalesce("phone", F.lit("")), "[^0-9+]", ""),
        1, 15,
    ),
)
# Check-list avant d'écrire une UDF : regexp_*, split, transform,
# aggregate, sequence, date_*, conv... couvrent l'immense majorité des cas.

Result

+--------------------+------------+
|               phone| phone_clean|
+--------------------+------------+
|+33 (0)6 12 34 56 78|+33612345678|
|      06-98-76-54-32|  0698765432|
|                null|            |
+--------------------+------------+

Sur 1.2 Md de lignes : UDF Python 312 s -> natif 9 s (x34)
PySparkUDFCatalystPerformance

Related snippets

Back to the Data Lab