Revenir au contenu principal

Requêtes paramétrées avec PySpark

Parameterized queries with PySpark

Publié: 3 janvier 2024

Open Source7 min de lecture

PySpark a toujours fourni d'excellentes API SQL et Python pour l'interrogation des données. Depuis Databricks Runtime 15.2 et Apache Spark 4.0, les requêtes paramétrées prennent en charge des moyens sûrs et expressifs d'interroger des données avec SQL en utilisant des paradigmes de programmation Pythoniques.

Cet article explique comment créer des requêtes paramétrées avec PySpark et quand il s'agit d'un bon modèle de conception pour votre code.

Les paramètres aident à rendre votre code Spark plus facile à réutiliser et à tester. Ils encouragent également les bonnes pratiques de codage. Cet article présentera deux manières différentes de paramétrer les requêtes PySpark :

  1. Le formatage de chaînes personnalisé de PySpark
  2. Les marqueurs de paramètres

Examinons comment utiliser les deux types de requêtes paramétrées PySpark et pourquoi la fonctionnalité intégrée est meilleure que d'autres alternatives.

Avantages des requêtes paramétrées

Les requêtes paramétrées encouragent le modèle « ne vous répétez pas » (DRY), facilitent les tests unitaires et rendent le SQL plus facile à réutiliser. Elles protègent également contre les attaques par injection SQL, qui peuvent présenter des vulnérabilités de sécurité.

Il peut être tentant de copier-coller de grands blocs de SQL lors de l'écriture de requêtes similaires. Les requêtes paramétrées encouragent l'abstraction des modèles et l'écriture de code selon le modèle DRY.

Les requêtes paramétrées sont également plus faciles à tester. Vous pouvez paramétrer une requête pour qu'elle soit facile à exécuter sur des jeux de données de production et de test.

En revanche, paramétrer manuellement les requêtes SQL avec des f-strings Python est une mauvaise alternative. Considérez les inconvénients suivants :

  1. Les f-strings Python ne protègent pas contre les attaques par injection SQL.
  2. Les f-strings Python ne comprennent pas les objets natifs Python tels que les DataFrames, les colonnes et les caractères spéciaux.

Examinons comment paramétrer les requêtes avec des marqueurs de paramètres, qui protègent votre code contre les vulnérabilités d'injection SQL et prennent en charge la conversion automatique de type des instances PySpark courantes au format chaîne.

Requêtes paramétrées avec le formatage de chaînes personnalisé de PySpark

Supposons que vous ayez la table de données suivante appelée h20_1e9 avec neuf colonnes :

Vous souhaitez paramétrer la requête SQL suivante :

Vous souhaitez faciliter l'exécution de cette requête avec différentes valeurs de id1. Voici comment paramétrer et exécuter la requête avec différentes valeurs de id1.

Réexécutez maintenant la requête avec un autre argument :

Le formateur de chaînes PySpark vous permet également d'exécuter des requêtes SQL directement sur un DataFrame sans définir explicitement de vues temporaires.

Supposons que vous ayez le DataFrame suivant appelé person_df :

Voici comment interroger le DataFrame avec SQL.

Exécuter des requêtes sur un DataFrame en utilisant la syntaxe SQL sans avoir à enregistrer manuellement une vue temporaire est très pratique !

Voyons maintenant comment paramétrer les requêtes avec des arguments dans des marqueurs de paramètres.

Requêtes paramétrées avec des marqueurs de paramètres

Vous pouvez également utiliser un dictionnaire d'arguments pour formuler une requête SQL paramétrée avec des marqueurs de paramètres.

Supposons que vous ayez la vue suivante nommée some_purchases :

Voici comment créer une requête paramétrée avec des marqueurs de paramètres nommés pour calculer le montant total dépensé pour un article donné.

Calculez le montant total dépensé pour les chaussettes.

Vous pouvez également paramétrer des requêtes avec des marqueurs de paramètres non nommés ; consultez ici pour plus d'informations.

Apache Spark assainit les marqueurs de paramètres, cette approche de paramétrisation vous protège donc également contre les attaques par injection SQL.

e-book

Démarrer avec l'ETL

Comment PySpark assainit les requêtes paramétrées

Voici une description générale de la manière dont Spark assainit les requêtes paramétrées nommées :

  • La requête SQL arrive avec une liste optionnelle de paramètres clé/valeur.
  • Apache Spark analyse la requête SQL et remplace les références de paramètres par des nœuds d'arbre d'analyse correspondants.
  • Lors de l'analyse, une règle Catalyst s'exécute pour remplacer ces références par les valeurs de paramètres fournies à partir des paramètres.
  • Cette approche protège contre les attaques par injection SQL car elle ne prend en charge que les valeurs littérales. L'interpolation de chaînes régulière applique la substitution sur la chaîne SQL ; cette stratégie peut être vulnérable aux attaques si la chaîne contient une syntaxe SQL autre que les valeurs littérales prévues.

Comme mentionné précédemment, il existe deux types de requêtes paramétrées prises en charge dans PySpark :

  • Paramétrage côté client utilisant la syntaxe {} basée sur PEP 3101 (nous avons appelé cela formatage de chaînes personnalisé).
  • Paramétrage côté serveur utilisant des marqueurs de paramètres nommés ou des marqueurs de paramètres non nommés.

La syntaxe {} effectue une substitution de chaîne sur la requête SQL côté client pour plus de facilité d'utilisation et une meilleure programmabilité. Cependant, elle ne protège pas contre les attaques par injection SQL car le texte de la requête est substitué avant d'être envoyé au serveur Spark.

Le paramétrage utilise l'argument args de l'API sql() et transmet le texte SQL et les paramètres séparément au serveur. Le texte SQL est analysé avec les espaces réservés aux paramètres, substituant les valeurs des paramètres spécifiés dans args dans l'arbre de requête analysé.

Il existe deux variantes de requêtes paramétrées côté serveur : les marqueurs de paramètres nommés et les marqueurs de paramètres non nommés. Les marqueurs de paramètres nommés utilisent la syntaxe :<nom_param> pour les espaces réservés. Consultez la documentation pour plus d'informations sur l'utilisation des marqueurs de paramètres non nommés.

Requêtes paramétrées vs interpolation de chaînes

Vous pouvez également utiliser l'interpolation de chaînes Python standard pour paramétrer des requêtes, mais ce n'est pas aussi pratique.

Voici comment nous devrions paramétrer notre requête précédente avec des f-strings Python :

Ce n'est pas aussi pratique pour les raisons suivantes :

  • Cela nécessite de créer une vue temporaire.
  • Nous devons représenter la date sous forme de chaîne, et non de date Python.
  • Nous devons entourer la date de guillemets simples dans la requête pour formater correctement la chaîne SQL.
  • Cela ne protège pas contre les attaques par injection SQL.

En résumé, les capacités de paramétrage de requêtes intégrées sont plus sûres et plus efficaces que l'interpolation de chaînes.

Conclusion

Les requêtes paramétrées PySpark vous offrent de nouvelles capacités pour écrire du code propre avec une syntaxe SQL familière. Elles sont pratiques lorsque vous souhaitez interroger un DataFrame Spark avec SQL. Elles vous permettent d'utiliser des types de données Python courants tels que les nombres à virgule flottante, les chaînes de caractères, les dates et les dates-heures, qui sont automatiquement convertis en valeurs SQL en arrière-plan. De cette façon, vous pouvez désormais exploiter les idiomes Python courants et écrire du code élégant.

Commencez à exploiter les requêtes paramétrées PySpark dès aujourd'hui, et vous profiterez immédiatement des avantages d'une base de code de meilleure qualité.

Cette fonctionnalité est officiellement prise en charge à partir de DBR 15.2.

(Cet article de blog a été traduit à l'aide d'outils basés sur l'intelligence artificielle) Article original

Ne manquez jamais un article Databricks

Abonnez-vous à notre blog et recevez les derniers articles dans votre boîte mail.