Veröffentlicht: 3. Januar 2024
von Matthew Powers, Daniel Tenedorio und Hyukjin Kwon
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:
Sehen wir uns an, wie beide Arten von parametrisierten PySpark-Abfragen verwendet werden und warum die integrierte Funktionalität besser ist als andere Alternativen.
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:
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.
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.
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.
Hier ist eine allgemeine Beschreibung, wie Spark benannte parametrisierte Abfragen bereinigt:
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.
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:
Zusammenfassend lässt sich sagen, dass die integrierten Funktionen zur Abfrageparametrisierung sicherer und effektiver sind als die String-Interpolation.
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
