DuckDB
Kernideen
- Wie SQLite ohne Server, aber für Auswertungen statt für Einzelzugriffe gebaut
- Fragt CSV- und Parquet-Dateien direkt ab, ohne sie vorher zu importieren
- Spaltenweise Speicherung: Aggregationen über viele Zeilen sind schnell
- Arbeitet mit Data Frames aus R und Python zusammen, ohne Kopie
- Volles analytisches SQL, inklusive Fensterfunktionen
- Für vieles der bessere Zwischenschritt als eine Serverdatenbank
Erklärung
Vorwissen: SQL für die Abfragen. Die Einordnung gegenüber den anderen Systemen steht in der Übersicht; die Formate CSV und Parquet behandelt Datenimport und Formate.
Wofür DuckDB gebaut ist
SQLite und die Serverdatenbanken sind darauf ausgelegt, einzelne Zeilen zu lesen und zu schreiben: eine Bestellung anlegen, einen Kunden nachschlagen. DuckDB ist auf die andere Art von Frage ausgelegt, die in der Datenarbeit die übliche ist: über viele Zeilen hinweg aggregieren, gruppieren, verbinden.
Der Unterschied liegt in der Speicherung. Zeilenweise organisierte Systeme lesen ganze Datensätze; DuckDB speichert spaltenweise und liest nur die Spalten, die in der Abfrage vorkommen. Bei einer Tabelle mit fünfzig Spalten, von denen drei gebraucht werden, ist das der Unterschied zwischen Sekunden und Minuten.
Wie SQLite läuft DuckDB im eigenen Prozess: kein Server, keine Installation über den Paketmanager der Sprache hinaus, keine Rechteverwaltung.
Dateien direkt abfragen
Der praktischste Punkt im Alltag: Es braucht keinen Import. CSV- und Parquet-Dateien lassen sich unmittelbar als Tabelle ansprechen, auch mehrere auf einmal über ein Muster im Dateinamen.
SELECT standort, COUNT(*) AS n, AVG(verbrauch) AS mittel
FROM 'messungen/*.parquet'
WHERE datum >= '2026-01-01'
GROUP BY standort
ORDER BY mittel DESC;Damit wird DuckDB zum Werkzeug für Dateien, die für den Arbeitsspeicher zu gross sind, ohne dass eine Datenbank aufgesetzt werden muss.
Zusammenspiel mit R und Python
DuckDB kann Data Frames der jeweiligen Sprache direkt als Tabelle ansprechen und Ergebnisse wieder als Data Frame zurückgeben. Damit lässt sich SQL genau dort einsetzen, wo es klarer ist als eine lange Kette von Wrangling-Schritten, ohne die Umgebung zu verlassen.
library(duckdb)
con <- dbConnect(duckdb())
duckdb_register(con, "messung", messung_df) # Data Frame als Tabelle
ergebnis <- dbGetQuery(con, "
SELECT standort, AVG(verbrauch) AS mittel
FROM messung GROUP BY standort")import duckdb
messung = pd.read_parquet("messung.parquet")
ergebnis = duckdb.sql("""
SELECT standort, AVG(verbrauch) AS mittel
FROM messung GROUP BY standort
""").df()In Python wird der Data Frame messung einfach über seinen Namen angesprochen; eine Registrierung ist nicht nötig.
Wann DuckDB, wann etwas anderes
| Fall | Passend |
|---|---|
| Grosse Dateien auswerten, einmal oder wiederholt | DuckDB |
| Wenige Zeilen laufend lesen und schreiben | SQLite oder Serverdatenbank |
| Mehrere Personen greifen gleichzeitig schreibend zu | PostgreSQL |
| Daten liegen bereits in einer Serverdatenbank | Dort aggregieren, siehe PostgreSQL |
| Ergebnisse langfristig aufbewahren und pflegen | Serverdatenbank |
Typische Aufgaben
Eine Datei ansehen, ohne sie zu laden
SELECT * FROM 'daten.csv' LIMIT 10;
DESCRIBE SELECT * FROM 'daten.csv'; -- Spalten und erkannte Typen
SELECT COUNT(*) FROM 'daten.parquet';Viele Dateien als eine Tabelle behandeln
SELECT * FROM read_parquet('messungen/*.parquet');
SELECT * FROM read_csv_auto('export_2026_*.csv', union_by_name = true);Formate umwandeln
COPY (SELECT * FROM 'gross.csv') TO 'gross.parquet' (FORMAT parquet);Parquet ist spaltenweise, komprimiert und typsicher; als Zwischenformat für grosse Zwischenstände ist es CSV deutlich überlegen.
Ergebnis zurück in die Sprache holen
df <- dbGetQuery(con, "SELECT * FROM 'gross.parquet' WHERE standort = 'Bern'")df = duckdb.sql("SELECT * FROM 'gross.parquet' WHERE standort = 'Bern'").df()Eine dauerhafte Datenbankdatei verwenden
con <- dbConnect(duckdb(), dbdir = "analyse.duckdb")verbindung = duckdb.connect("analyse.duckdb")Aus einer anderen Datenbank lesen
INSTALL postgres; LOAD postgres;
ATTACH 'dbname=produktion host=db.example.org' AS pg (TYPE postgres);
SELECT COUNT(*) FROM pg.public.bestellung;So lassen sich Daten aus einer Serverdatenbank mit lokalen Dateien in einer einzigen Abfrage verbinden.
Verständnisfragen
Die Beispiele auf dieser Seite sind Listings: DuckDB ist in der Umgebung, die diese Website baut, nicht installiert, deshalb wird hier nichts gerechnet. Wo Abfragen wirklich laufen, steht es dabei, etwa unter SQL und SQLite.
Eine Parquet-Datei mit 80 Millionen Zeilen und 60 Spalten soll nach Monat aggregiert werden; drei Spalten werden gebraucht. Was ist der schnellste Weg?
Warum ist die spaltenweise Speicherung für Auswertungen im Vorteil, für eine Bestellanwendung aber nicht?
Wann ist SQLite die bessere Wahl als DuckDB?
In Python lässt sich ein pandas-DataFrame in DuckDB über seinen Namen abfragen, ohne ihn zu importieren. Was bedeutet das für den Arbeitsspeicher?