Seit 2014 ist Snowflake Inc. mit dem gleichnamigen Clouddatawarehouse am Markt. In den vergangenen Jahren konnte Snowflake dabei eine rasante Entwicklung erfahren und wird heute branchenübergreifend eingesetzt. Haupttreiber für den großen Erfolg ist die besondere Architektur von Snowflake, da das Datawarehouse, anders als viele Wettbewerber, ausschließlich und nativ für die Cloud entwickelt wurde und daher mit herausragender Skalierbarkeit und Performance punkten kann. Aktuell steht Snowflake auf AWS, Azure und GCP zur Verfügung und überzeugt dort mit weiteren Vorteilen, unter anderem der unabhängigen Skalierbarkeit von Storage- und Computeressourcen, ausgeprägten Datasharing Möglichkeiten und einem schnell wachsenden Partnernetzwerk. Mittlerweile erstrecken sich die Kapazitäten von Snowflake weit über das eigentliche Datawarehousing hinaus, da zunehmend auch weitere Workflows wie Data Engineering oder Data Science unterstützt werden, sodass eine sogenannte Cloud-Dataplattform entsteht.
Heterogener Nutzerkreis
Die Nutzerschaft von Daten in Snowflake und im Allgemeinen ist typischerweise stark heterogen. Auf der einen Seite finden sich Mitarbeiter aus Fachdomänen, welche oftmals in erster Linie mit graphischen Tools arbeiten, und Analysten, welche etwa direkt mit SQL auf den Daten operieren. Auf der anderen Seite stellen Data Engineers und Data Scientists eine wichtige Nutzergruppe dar, welche häufig mit Tools wie Pandas oder Spark auf und mit den Daten arbeitet. Snowflake zollt den unterschiedlichen Nutzern und ihrem Programmier-Knowhow Tribut, indem diverse Tools und GUIs angeboten werden, welche die Vorlieben und Skills der Nutzer respektieren. So können mit dem Web-GUI Snowsight mit wenigen Mausklicks Graphiken basierend auf SQL Queries generiert werden, während SnowSQL als CLI-Tool einen SQL und codebasierten Zugriff auf sämtliche DDL- und DML-Operationen erlaubt. Für die letztgenannte Gruppe der Data Engineers und Scientists steht indes Snowpark zur Verfügung, welches im weiteren Verlauf des Artikels beschrieben wird.
Snowpark Basics
Mit Snowpark bietet Snowflake eine intuitive Data Frame API für den Zugriff auf und die Prozessierung von Daten in Snowflake sowie für den Ingest von Daten in die Snowflake an. Dabei kann zwischen den Programmiersprachen Java, Scala und Python gewählt werden, in welchen auch benutzerdefinierte Logik in Form von User-Defined Functions (UDFs) formuliert werden kann. Die Ausführung sämtlicher Logik der Dataframe API erfolgt direkt in der Sowflake unter Nutzung der dort provisionierten Computeressourcen. Nutzer haben dabei zudem die Option, UDFS bereits im Vorfeld über die Nutzung der Weboberfläche in den Programmiersprachen Java, Python und JavaScript zu definieren und dann in Snowpark zu referenzieren und damit zu verwenden.
Getting Started mit Snowpark
Die Verwendung von Snowpark zeichnet sich durch geringe Voraussetzungen aus. So wird neben einem Snowflake Account (auch ein kostenfreier Trialaccount ist möglich) lediglich eine Clientmaschine benötigt, auf welcher eine Installation von Java, Scala oder Python samt korrespondierender Snowpark Library vorhanden ist. Die Systemanforderungen für die Clientmaschine sind dabei minimal, da das Gros der Berechnungen via Pushdown in der Snowflake erfolgt.
Sind die Anforderungen erst einmal erfüllt, braucht es lediglich eine Snowparksession, welche die Verbindung zur Snowflake herstellt. Diese kann etwa in Scala wie folgt erzeugt werden:
import com.snowflake.snowpark._
val snowflakeConfigMap = Map(
"URL" -> sys.env(SnowflakeUrl),
"USER" -> sys.env(SnowflakeUser),
"PASSWORD" -> sys.env(SnowflakePassword),
"ROLE" -> sys.env(SnowflakeRole),
"WAREHOUSE" -> sys.env(SnowflakeWarehouse),
"DB" -> sys.env(SnowflakeDatabase),
"SCHEMA" -> sys.env(SnowflakeSchema)
)
val session = Session.builder.configs(snowflakeConfigMap).create
val df = session.sql("SELECT country, amount from products")
Snowpark Funktionsprinzip
Das Funktionsprinzip glänzt ebenfalls durch geringe Komplexität gegenüber dem Anwender. Die in Dataframes formulierte Logik wird zur Laufzeit auf der Clientmaschine in SQL Code übersetzt, welcher dann über den Sowflake Connector an die Snowflake transferiert und dort ausgeführt wird. Bei der Nutzung von UDFs wird ergänzend ein Object Serializer aufgerufen, um den Code für die Ausführung in die Snowflake zu transferieren.
Die Nutzung von Snowpark wartet mit diversen Vorteilen auf. Zunächst werden im Data Engineering und Data Science Milieu beliebte Programmiersprachen und eine wohlbekannte Dataframe API angeboten. Des Weiteren kann die Skalierbarkeit und Leistungsfähigkeit der Snowflake ideal genutzt werden, inklusive der Provisionierung von hoch performanten Rechenclustern binnen weniger Sekunden. Zuletzt wird die Dataframe Logik durch UDFs partiell benutzerdefinierbar. Sollte das noch nicht genügen, kann auf der Clientmaschine aber auch ergänzend gänzlich benutzerdefinierter Code ausgeführt und mit der Dataframe API kombiniert werden, was im folgenden Beispiel demonstriert wird.
Praxisbeispiel – GraphQL API
Sensordaten werden über eine GraphQL API zur Verfügung gestellt. Diese Daten sollen zu Auswertungszwecken in die Snowflake geladen und transformiert werden. Ein Client zum Abfragen der API ist in Snowflake nicht nativ vorhanden, lässt sich aber in Python, Scala oder Java dank zahlreicher Libraries mit wenig Aufwand implementieren. Die Antwort der API sei ein JSON String, welcher direkt via Dataframe API in die Snowflake in eine Stagingtabelle geschrieben werden kann. Dazu kann der Variant-Datentyp von Snowflake verwendet werden, welcher semistrukturierte Daten mit einer Größe von bis zu 16 MB aufnehmen kann. Das Parsing des JSON und diverse weitere Transformationen der Daten können ebenfalls mittels Dataframe API formuliert werden.
Aufpassfeld Variant
Die Limitierung von Daten mit einer maximalen Größe von 16 MB für den Variant-Datentyp kann je nach Struktur der Antwort der API zu Problemen führen. Antworten von APIs etwa geben die einzelnen Messpunkte typischerweise als Array zurück, welches wiederum Teil eines Headers sein kann. Hier als Beispiel:
{
“data”: {
“events”: [
{
“fld1”: “someValue”,
“fld2”: “anyValue”
},
{
“fld1”: “myValue”,
“fld2”: “thisValue”
},
{
…
}
]
}
}
Um diesem Problem zu begegnen, kann erneut mit benutzerdefinierter Logik gearbeitet werden, indem auf die Daten bereits vor dem Schreiben nach Snowflake ein initiales Parsing angewandt wird. Im Falle des skizzierten Beispiels kann etwa das Array mit den eigentlichen Messpunkten extrahiert und dann problemlos in die Snowflake geschrieben werden.
Vorzüge von Snowpark
Auf diese Weise werden clientseitig lediglich die hochgradig benutzerdefinierten Ausführungsschritte vorgenommen, während alle übrigen Transformationen via Pushdown in der Snowflake ausgeführt werden. Der gesamte Quellcode ist dabei in einer einzigen Programmiersprache formuliert und es benötigt somit lediglich ein Coderepository. Die eigentliche Ausführung lässt sich etwa mit einem Dockerimage und einem Containerservice wie Kubernetes oder Openshift umsetzen, sodass sich insgesamt mit geringem Aufwand eine durchgängige CI/CD Pipeline installieren lässt.