2022-10-12
Modern Data Stack in a Box mit DuckDB
Guest post by Jacob Matson

Dieser Beitrag ist eine Zusammenarbeit mit Jacob Matson und erscheint auch auf dataduel.co.
Zusammenfassung
Es gibt eine große Menge Literatur, z. B. 1 und 2, über das Skalieren von Datenpipelines. „Nutzt Kafka! Baut ein Lakehouse! Baut kein Lakehouse, nutzt Snowflake! Nutzt nicht Snowflake, nutzt XYZ!“ Mit Fortschritten bei Hardware und der raschen Reife von Datensoftware gibt es jedoch einen einfacheren Weg. Dieser Artikel zeigt den Weg zu hochperformanter Single-Node-Analytik mit einem quelloffenen MDS-in-a-box-Stack: Meltano, DuckDB, dbt und Apache Superset unter Windows mit Windows Subsystem for Linux (WSL). Es gibt viele Optionen innerhalb des MDS. Wenn Sie einen anderen Stack nutzen, um ein MDS-in-a-box zu bauen, teilen Sie ihn bitte mit der Community auf DuckDB Twitter, GitHub oder Discord oder im dbt Slack! Oder schauen Sie einfach vorbei für eine freundliche Debatte über unsere Werkzeugwahl!
Motivation
Was ist der Modern Data Stack, und warum ihn nutzen? Der MDS kann vieles bedeuten (siehe Beispiele und eine historische Einordnung), im Kern ist er aber die Rückkehr zu SQL für Datentransformationen durch die Kombination mehrerer Best-in-Class-Softwarewerkzeuge zu einem Stack. Ein typischer Stack umfasst (zumindest!) ein Werkzeug, das Daten aus Quellen extrahiert und in ein Data Warehouse lädt, dbt zum Transformieren und Analysieren dieser Daten im Warehouse und ein Business-Intelligence-Werkzeug. Der MDS nutzt die Zugänglichkeit von SQL zusammen mit Softwareentwicklungs-Best-Practices wie Git, damit Analysten ihre Wirkung in ihren Unternehmen skalieren können.
Warum einen gebündelten Modern Data Stack auf einer einzelnen Maschine bauen, statt auf mehreren Maschinen und einem Data Warehouse? Es gibt viele Vorteile!
- Vereinfachen für höhere Entwicklerproduktivität
- Kosten senken, indem das Data Warehouse entfällt
- Einfach lokal, on-premise, in der Cloud oder in allen drei Varianten bereitstellen
- Softwarekosten eliminieren mit einem vollständig freien und quelloffenen Stack
- Hohe Leistung halten mit moderner Software wie DuckDB und immer leistungsfähigeren Single-Node-Recheninstanzen
- Autarkie erreichen, indem Sie einen End-to-End-Proof-of-Concept auf dem Laptop abschließen
- Entwicklungs-Best-Practices durch Integration mit GitHub ermöglichen
- Sicherheit erhöhen, indem (optional) alles lokal oder on-premise läuft
Wenn Sie zu einer Open-Source-Community beitragen oder ein Produkt innerhalb des Modern Data Stack anbieten, gibt es einen zusätzlichen Nutzen!
- Die Adoption Ihres Werkzeugs steigern, indem Sie einen freien, in sich geschlossenen Beispiel-Stack bereitstellen
- Dagsters Beispielprojekt nutzt DuckDB dafür bereits!
- Melden Sie sich auf DuckDB Twitter, GitHub oder Discord oder im dbt Slack, um ein Beispiel mit Ihrem Werkzeug mit der Community zu teilen!
Abwägungen
Eine Kernkomponente des MDS ist die unbegrenzte Skalierbarkeit von Compute. Wie passt das zum MDS-in-a-box-Ansatz? Heute können Cloud-Recheninstanzen deutlich stärker vertikal skalieren als früher (z. B. 224 Kerne und 24 TB RAM auf AWS!). Laptops sind leistungsfähiger denn je. Da neue OLAP-Werkzeuge wie DuckDB diese Rechenleistung besser nutzen können, ist horizontale Skalierung für viele Analysen nicht mehr nötig! Außerdem lässt sich dieses MDS-in-a-box leicht auf so viele Boxen verdoppeln, wie nötig, wenn nach Fachgebiet partitioniert wird. Unendliches Compute wird also geopfert, erheblicher Maßstab bleibt aber leicht erreichbar.
Durch diesen Kompromiss ist der Ansatz eher ein „Open Source Analytics Stack in a box“ als ein traditioneller MDS. Er opfert unendliche Skalierung für deutliche Vereinfachung und die anderen Vorteile oben.
Ein Problem wählen
Da die NBA-Saison bald beginnt, ist eine Monte-Carlo-artige Simulation der Saison sowohl aktuell als auch gut für analytisches SQL geeignet. Das ist ein besonders gutes Szenario, um die Grenzen von DuckDB zu testen, weil es nur einfache Eingaben braucht und leicht auf enorme Satzzahlen skaliert. Das gesamte Projekt liegt in einem GitHub-Repo, das Sie auf GitHub finden.
Die Umgebung aufbauen
Die detaillierten Schritte zum Aufbau des Projekts stehen im Repo, die groben Schritte wiederholen wir hier. Hinweis: Windows Subsystem for Linux (WSL) wurde gewählt, um Apache Superset zu unterstützen, die anderen Komponenten dieses Stacks können direkt auf jedem Betriebssystem laufen. Glücklicherweise ist Linux unter Windows sehr unkompliziert geworden.
- Ubuntu 20.04 unter WSL installieren.
- Pakete aktualisieren (
sudo apt update). - Python installieren.
- Das Git-Repo klonen.
- Im Terminal
make buildund dannmake runausführen. - Super-Admin-Nutzer für Superset im Terminal anlegen, dann einloggen und die Datenbank konfigurieren.
- Testabfragen in Superset ausführen, um Ihre Arbeit zu prüfen.
Meltano als Wrapper für Pipeline-Plugins
In diesem Beispiel zieht Meltano mehrere Bits und Pieces zusammen, damit die Pipeline mit einem einzigen Statement laufen kann. Der erste Teil ist der Tap (Extractor) ‚tap-spreadsheets-anywhere‘. Dieser Tap erlaubt es, flache Datendateien aus verschiedenen Quellen zu holen. Hinweis: DuckDB kann direkt aus flachen Dateien konsumieren (lokal und über das Netz) oder aus SQLite- und PostgreSQL-Datenbanken. Dieser Tap wurde jedoch gewählt, um ein klares Beispiel dafür zu geben, statische Daten in Ihre Datenbank zu bringen, die sich leicht in der Datei meltano.yml konfigurieren lassen. Meltano wird außerdem nützlicher, je komplexer Ihre Datenquellen werden.
plugins: extractors: - name: tap-spreadsheets-anywhere variant: ets pip_url: git+https://github.com/ets/tap-spreadsheets-anywhere.git# data sources are configured inside of this extractorAls Nächstes der Target (Loader) ‚target-duckdb‘. Dieses Target kann Daten aus jedem Meltano-Tap entgegennehmen und in DuckDB laden. Ein Teil der Schönheit dieses Ansatzes: Sie müssen sich nicht mit der Extra-Komplexität einer typischen Datenbank herumschlagen. DuckDB kann eingelegt werden und ist ohne Konfiguration oder laufende Wartung einsatzbereit. Weil die Komponenten und die Daten am selben Ort liegen, ist Networking kein Thema und die Komplexität sinkt weiter.
loaders: - name: target-duckdb variant: jwills pip_url: target-duckdb~=0.4 config: filepath: /tmp/mdsbox.db default_target_schema: mainAls Nächstes der Transformer: ‚dbt-duckdb‘. dbt ermöglicht Transformationen mit einer Kombination aus SQL und Jinja-Templating für zugängliches SQL-basiertes Analytics Engineering. Der dbt-Adapter für DuckDB unterstützt jetzt parallele Ausführung über Threads, was das MDS-in-a-box noch schneller macht. Da der Großteil der Arbeit in dbt passiert, wird dieser Teil später im Beitrag genauer beschrieben.
transformers: - name: dbt-duckdb variant: jwills pip_url: dbt-core~=1.2.0 dbt-duckdb~=1.2.0 config: path: /tmp/mdsbox.dbZuletzt ist Apache Superset als Meltano-Utility enthalten, um Datenabfragen und Visualisierung zu ermöglichen. Superset nutzt DuckDBs SQLAlchemy-Treiber duckdb_engine, kann DuckDB also ebenfalls direkt abfragen.
utilities: - name: superset variant: apache pip_url: apache-superset==1.5.0 markupsafe==2.0.1 duckdb-engine==0.6.4Bei Superset muss die Engine so konfiguriert werden, dass DuckDB im „Read-only“-Modus geöffnet wird. Sonst kann nur eine Abfrage gleichzeitig laufen (gleichzeitige Abfragen verursachen Locks). Das verhindert auch das Aktualisieren des Superset-Dashboards, während die Pipeline läuft. In diesem Fall läuft die Pipeline in unter 8 Sekunden!
Die Daten aufbereiten
Der NBA-Spielplan wurde von basketball-reference.com heruntergeladen, und die Draft-Kings-Sieg-Totals vom 27. September wurden für die Sieg-Totals genutzt. Spielplan und Sieg-Totals bilden die gesamte für dieses Projekt nötige Eingabe. Nach der Umwandlung ins CSV-Format wurden sie ins GitHub-Projekt hochgeladen, und die Datei meltano.yml wurde aktualisiert, um auf die Dateipfade zu verweisen.
Sources laden
Sobald die Daten im Web auf GitHub liegen, kann Meltano eine Kopie nach DuckDB ziehen. Mit dem Befehl meltano run tap-spreadsheets-anywhere target-duckdb werden die Daten in DuckDB geladen und sind bereit für die Transformation in dbt.
dbt-Modelle bauen
Nachdem die Sources geladen sind, werden die Daten mit dbt transformiert. Zuerst werden die Source-Modelle sowie der Szenario-Generator angelegt. Dann werden die Zufallszahlen für diesen Simulationslauf erzeugt – die Zufallszahlen werden als Tabelle, nicht als View, festgehalten, damit nachfolgende erneute Läufe der Downstream-Modelle mit den Graph-Operatoren zum Debuggen möglich sind (z. B. dbt run -s random_num_gen+). Sobald die zugrunde liegenden Daten liegen, beginnt die Simulation, zuerst die Regular Season, dann die Play-in-Spiele und zuletzt die Playoffs. Da jede Spielrunde von der vorherigen abhängt, ist die Parallelisierung in diesem Modell begrenzt, was sich im dbt-DAG widerspiegelt, in diesem Fall bequem auf GitHub Pages gehostet.
Es gibt ein paar weitere Designentscheidungen, die sich lohnen zu erwähnen:
- Simulations- und Summary-Tabellen wurden in getrennte Modelle aufgeteilt, für leichtere Nutzung und Transparenz. Jede Simulationsrunde hat also ein Sim-Modell und ein End-Modell – so können die richtigen Parameter (Conference, Team, Elo-Rating) in jede folgende Runde übergeben werden.
- Um zu tiefe Abfragen zu vermeiden, wurden
reg_season_endundplayoff_sim_r1als Tabellen materialisiert. Das ist beim Build etwas langsamer, die Leistungsgewinne beim Abfragen von Summary-Tabellen (z. B.season_summary) sind den Slowdown aber mehr als wert. Hinweis: Schon bei nur 10.000 Sims braucht die Datenbank etwa 150 MB auf der Platte. Bei 100.000 Simulationen wächst sie leicht auf ein paar GB.
Superset anbinden
Sobald die dbt-Modelle gebaut sind, kann die Datenvisualisierung beginnen. In Superset muss ein Admin-Nutzer angelegt werden, um sich einzuloggen. Die Anleitung zum Verbinden der Datenbank steht im GitHub-Projekt, ebenso ein Hinweis, wie man sie im „Read-only“-Modus verbindet.
Es gibt 2 Modelle für die Analyse, obwohl beliebig viele genutzt werden können. season_summary enthält verschiedene Summary-Statistiken für die Saison, und reg_season_sim enthält alle simulierten Spielergebnisse. Dieser zweite Datensatz erzeugt ein interessantes Histogramm. Um Datenvisualisierungen in Superset zu bauen, muss zuerst der Datensatz definiert, dann das Chart gebaut und zuletzt das Chart einem Dashboard zugewiesen werden.
Unten ein Beispiel-Superset-Dashboard mit mehreren Charts auf Basis dieser Daten. Superset kann die Daten klar zusammenfassen und das Ausmaß der Variabilität in der Monte-Carlo-Simulation zeigen. Die duckdb_engine-Abfragen lassen sich schnell aktualisieren, wenn neue Simulationen laufen.


Fazit
Das Ökosystem um DuckDB ist so gewachsen, dass es sich gut in den Modern Data Stack einfügt. Das MDS-in-a-box ist ein tragfähiger Ansatz für kleinere Datenprojekte und würde besonders gut für leselastige Analytik funktionieren. Es gab ein paar weitere Learnings aus diesem Experiment. Superset-Dashboards sind leicht zu bauen, aber sie sind nicht skriptbar und müssen in der GUI gebaut werden (die bezahlte gehostete Version, Preset, unterstützt den Export als YAML). Außerdem: Monte-Carlo-Analysen in SQL gehen, in einer anderen Sprache können sie aber leichter sein. Das zeigt jedoch, wie weit sich die Fähigkeiten von SQL dehnen lassen!
Nächste Schritte
Es gibt weitere Richtungen für dieses Projekt. Ein nächster Schritt könnte sein, diesen Workflow zu dockerisieren, für noch einfachere Deployments. Wenn Sie ein Docker-Beispiel zusammenstellen möchten, schreiben Sie uns! Eine andere Anpassung des Ansatzes könnte sein, die finalen Ausgaben in Parquet-Dateien zu landen und sie mit In-Memory-DuckDB-Verbindungen zu lesen. Diese Dateien könnten sogar in einem S3-kompatiblen Object Store landen (und trotzdem von DuckDB gelesen werden), das fügt gegenüber dem In-a-box-Ansatz jedoch Komplexität hinzu! Weitere MDS-Komponenten könnten auch für Data-Quality-Monitoring, Lineage-Tracking usw. integriert werden.
Josh Wills arbeitet außerdem an einer interessanten Erweiterung von dbt-duckdb! Mit der Bibliothek sqlglot könnte dbt-duckdb dbt-Modelle, die im SQL-Dialekt anderer Datenbanken (einschließlich Snowflake und BigQuery) geschrieben sind, automatisch nach DuckDB transpilieren. Stellen Sie sich vor, Sie könnten Ihre Abfragen lokal testen, bevor Sie sie in Produktion pushen… Kommen Sie in den DuckDB-Kanal des dbt Slack, um die Möglichkeiten zu diskutieren!
Schreiben Sie uns, wenn Sie diesen oder einen anderen Ansatz nutzen, um ein MDS-in-a-box zu bauen! Wenn Sie einen Gastbeitrag für den DuckDB-Blog schreiben möchten, melden Sie sich auf Discord!