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:
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
Abonnieren Sie unseren Blog und erhalten Sie die neuesten Beiträge direkt in Ihren Posteingang.