Direkt zum Hauptinhalt

Parametrisierte Abfragen mit PySpark

Parameterized queries with PySpark

Veröffentlicht: 3. Januar 2024

Open-Source6 min Lesezeit

PySpark bietet schon immer wunderbare SQL- und Python-APIs für die Datenabfrage. Ab Databricks Runtime 15.2 und Apache Spark 4.0 unterstützen parametrisierte Abfragen sichere und ausdrucksstarke Wege, um Daten mit SQL unter Verwendung von Python-Programmierparadigmen abzufragen.

Dieser Beitrag erklärt, wie parametrisierte Abfragen mit PySpark erstellt werden und wann dies ein gutes Entwurfsmuster für Ihren Code ist.

Parameter machen Ihren Spark-Code einfacher wiederverwendbar und testbar. Sie fördern auch gute Programmierpraktiken. Dieser Beitrag zeigt die zwei verschiedenen Möglichkeiten zur Parametrisierung von PySpark-Abfragen:

  1. PySpark benutzerdefinierte String-Formatierung
  2. Parameter-Marker

Sehen wir uns an, wie beide Arten von parametrisierten PySpark-Abfragen verwendet werden und warum die integrierte Funktionalität besser ist als andere Alternativen.

Vorteile von parametrisierten Abfragen

Parametrisierte Abfragen fördern das „Don't Repeat Yourself“ (DRY)-Muster, erleichtern Unit-Tests und machen SQL wiederverwendbarer. Sie verhindern auch SQL-Injection-Angriffe, die Sicherheitslücken darstellen können.

Es kann verlockend sein, große SQL-Teile zu kopieren und einzufügen, wenn ähnliche Abfragen geschrieben werden. Parametrisierte Abfragen fördern die Abstraktion von Mustern und das Schreiben von Code nach dem DRY-Muster.

Parametrisierte Abfragen sind auch einfacher zu testen. Sie können eine Abfrage parametrisieren, sodass sie einfach auf Produktions- und Testdatensätzen ausgeführt werden kann.

Andererseits ist die manuelle Parametrisierung von SQL-Abfragen mit Python f-Strings eine schlechte Alternative. Berücksichtigen Sie die folgenden Nachteile:

  1. Python f-Strings schützen nicht vor SQL-Injection-Angriffen.
  2. Python f-Strings verstehen keine nativen Python-Objekte wie DataFrames, Spalten und Sonderzeichen.

Sehen wir uns an, wie Abfragen mit Parameter-Markern parametrisiert werden, die Ihren Code vor SQL-Injection-Schwachstellen schützen und die automatische Typkonvertierung gängiger PySpark-Instanzen im String-Format unterstützen.

Parametrisierte Abfragen mit benutzerdefinierter String-Formatierung in PySpark

Angenommen, Sie haben die folgende Datentabelle namens h20_1e9 mit neun Spalten:

Sie möchten die folgende SQL-Abfrage parametrisieren:

Sie möchten es einfach machen, diese Abfrage mit unterschiedlichen Werten für id1 auszuführen. Hier erfahren Sie, wie Sie die Abfrage parametrisieren und mit unterschiedlichen id1-Werten ausführen.

Führen Sie die Abfrage nun mit einem anderen Argument erneut aus:

Der PySpark-String-Formatter ermöglicht es Ihnen auch, SQL-Abfragen direkt auf einem DataFrame auszuführen, ohne explizit temporäre Ansichten zu definieren.

Angenommen, Sie haben den folgenden DataFrame namens person_df:

Hier erfahren Sie, wie Sie den DataFrame mit SQL abfragen.

Das Ausführen von Abfragen auf einem DataFrame mit SQL-Syntax, ohne eine temporäre Ansicht manuell registrieren zu müssen, ist sehr praktisch!

Sehen wir uns nun an, wie Abfragen mit Argumenten in Parameter-Markern parametrisiert werden.

Parametrisierte Abfragen mit Parameter-Markern

Sie können auch ein Dictionary von Argumenten verwenden, um eine parametrisierte SQL-Abfrage mit Parameter-Markern zu formulieren.

Angenommen, Sie haben die folgende Ansicht namens some_purchases:

Hier erfahren Sie, wie Sie eine parametrisierte Abfrage mit benannten Parameter-Markern erstellen, um den Gesamtbetrag für einen bestimmten Artikel zu berechnen.

Berechnen Sie den Gesamtbetrag für Socken.

Sie können Abfragen auch mit unbenannten Parameter-Markern parametrisieren; weitere Informationen finden Sie hier.

Apache Spark bereinigt Parameter-Marker, sodass dieser Parametrisierungsansatz Sie auch vor SQL-Injection-Angriffen schützt.

E-Book

Erste Schritte mit ETL

Wie PySpark parametrisierte Abfragen bereinigt

Hier ist eine allgemeine Beschreibung, wie Spark benannte parametrisierte Abfragen bereinigt:

  • Die SQL-Abfrage kommt mit einer optionalen Schlüssel/Wert-Parameterliste an.
  • Apache Spark analysiert die SQL-Abfrage und ersetzt die Parameterreferenzen durch entsprechende Parse-Tree-Knoten.
  • Während der Analyse wird eine Catalyst-Regel ausgeführt, um diese Referenzen durch die bereitgestellten Parameterwerte aus den Parametern zu ersetzen.
  • Dieser Ansatz schützt vor SQL-Injection-Angriffen, da er nur Literalwerte unterstützt. Normale String-Interpolation wendet die Substitution auf den SQL-String an; diese Strategie kann anfällig für Angriffe sein, wenn der String SQL-Syntax enthält, die über die beabsichtigten Literalwerte hinausgeht.

Wie bereits erwähnt, gibt es zwei Arten von parametrisierten Abfragen, die in PySpark unterstützt werden:

Die {}-Syntax führt eine String-Substitution in der SQL-Abfrage auf der Clientseite durch, um die Benutzerfreundlichkeit und Programmierbarkeit zu verbessern. Sie schützt jedoch nicht vor SQL-Injection-Angriffen, da der Abfragetext ersetzt wird, bevor er an den Spark-Server gesendet wird.

Die Parametrisierung verwendet das args-Argument der sql()-API und übergibt den SQL-Text und die Parameter getrennt an den Server. Der SQL-Text wird mit den Platzhaltern für Parameter analysiert, wobei die Werte der in args angegebenen Parameter im analysierten Abfragebaum ersetzt werden.

Es gibt zwei Varianten von serverseitigen parametrisierten Abfragen: benannte Parameter-Marker und unbenannte Parameter-Marker. Benannte Parameter-Marker verwenden die :<param_name>-Syntax für Platzhalter. Weitere Informationen zur Verwendung von unbenannten Parameter-Markern finden Sie in der Dokumentation.

Parametrisierte Abfragen im Vergleich zu String-Interpolation

Sie können auch reguläre Python-String-Interpolation zur Parametrisierung von Abfragen verwenden, aber das ist nicht so praktisch.

Hier ist, wie wir unsere vorherige Abfrage mit Python f-Strings parametrisieren müssten:

Das ist aus folgenden Gründen nicht so gut:

  • Es erfordert die Erstellung einer temporären Ansicht.
  • Wir müssen das Datum als String und nicht als Python-Datum darstellen.
  • Wir müssen das Datum in einfache Anführungszeichen in der Abfrage setzen, um den SQL-String richtig zu formatieren.
  • Dies schützt nicht vor SQL-Injection-Angriffen.

Zusammenfassend lässt sich sagen, dass die integrierten Funktionen zur Abfrageparametrisierung sicherer und effektiver sind als die String-Interpolation.

Fazit

PySpark-parametrisierte Abfragen eröffnen Ihnen neue Möglichkeiten, sauberen Code mit vertrauter SQL-Syntax zu schreiben. Sie sind praktisch, wenn Sie einen Spark DataFrame mit SQL abfragen möchten. Sie ermöglichen die Verwendung gängiger Python-Datentypen wie Gleitkommazahlen, Zeichenketten, Daten und Zeitstempel, die im Hintergrund automatisch in SQL-Werte umgewandelt werden. Auf diese Weise können Sie jetzt gängige Python-Idiome nutzen und eleganten Code schreiben.

Nutzen Sie PySpark-parametrisierte Abfragen noch heute und Sie werden sofort die Vorteile einer qualitativ hochwertigeren Codebasis genießen.

Dieses Feature wird offiziell ab DBR 15.2 unterstützt.

(Dieser Blogbeitrag wurde mit KI-gestützten Tools übersetzt.) Originalbeitrag

Verpassen Sie keinen Beitrag von Databricks

Abonnieren Sie unseren Blog und erhalten Sie die neuesten Beiträge direkt in Ihren Posteingang.