Direkt zum Hauptinhalt
Open-Source

Parametrisierte Abfragen mit PySpark

von Matthew Powers, Daniel Tenedorio und Hyukjin Kwon

Archived. This article has not been updated since the publish date above. The dynamic nature of information means that previously accurate content can become outdated or even obsolete over time. Readers are advised to exercise due diligence and cross-check any information found in this blog post before making decisions or adopting any practices based on said information.

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.

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

Erhalten Sie die neuesten Beiträge in Ihrem Posteingang

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