2023-04-14

Die Rückkehr des H2O.ai Database-like Ops Benchmark

Tom Ebergen

Direkt zu den Ergebnissen

Im November 2023 haben wir einen neuen Blogbeitrag zum H2O.ai-Benchmark veröffentlicht und das Setup für bessere Reproduzierbarkeit überarbeitet. Details im neuen Beitrag: „Aktualisierungen des H2O.ai db-benchmark!“

Der H2O.ai Database-like Ops Benchmark ist in der Datenanalyse- und R-Community ein bekannter Benchmark. Er misst die Group-by- und Join-Leistung verschiedener analytischer Werkzeuge wie data.table, Polars, dplyr, ClickHouse, DuckDB und weiterer. Seit dem 2. Juli 2021 ruhte der Benchmark: keine neuen Ergebnisse, keine Wartung. Viele der gemessenen Systeme haben sich seither stark verbessert, und viele Maintainer wollten wissen, wo ihr Werkzeug heute steht.

DuckDB hat beschlossen, dem H2O.ai-Benchmark neues Leben einzuhauchen und ihn auf absehbare Zeit zu pflegen. Ein Grund: Seit den letzten veröffentlichten Ergebnissen vom 2. Juli 2021 hatte DuckDB 10 neue Minor-Releases. Nachdem Teile des Benchmarks auf einer AWS-Box r3-8xlarge liefen, lag DuckDB unter den Besten. Außerdem will das DuckDB-Projekt zeigen, dass Leistung ernst genommen wird, indem DuckDB regelmäßig mit anderen analytischen Systemen verglichen wird. DuckDB zeichnet sich durch einfache Nutzung aus – Rohleistung und Skalierbarkeit bleiben aber entscheidend, um harte Probleme schnell zu lösen. Und wie viele andere im Datenumfeld haben wir Bedarf an Geschwindigkeit. Deshalb wurde der Benchmark geforkt, die Abhängigkeiten modernisiert und auf den neuesten Versionen der enthaltenen Systeme ausgeführt. Das Repository liegt auf GitHub.

Die Ergebnisse des neuen Benchmarks sind interessant. Zuerst aber eine kurze Zusammenfassung des Benchmarks und der Änderungen.

Der H2O.ai Database-like Ops Benchmark

Es gibt 5 grundlegende und 5 erweiterte Grouping-Tests. Die 10 Grouping-Abfragen drehen sich um Kombinationen aus:

Jede Abfrage wird nur zweimal ausgeführt, beide Ergebnisse werden berichtet. So sieht man die Leistung eines kalten Laufs und mögliche Caching-Effekte. Absichtlich wird kein potenzielles „Best“-Ergebnis auf einem heißen System berichtet. Datenanalysten brauchen eine Abfrage einmal, um ihre Antwort zu bekommen. Niemand fährt ein zweites Mal zum Laden, um einen Liter Milch schneller zu holen.

Die berichtete Zeit ist die Summe der Zeiten aller 5 Abfragen, jeweils zweimal ausgeführt.

Mehr zu den konkreten Abfragen weiter unten.

Die Daten und Abfragen

Die Abfragen haben sich seit dem Stillstand des Benchmarks nicht geändert. Die Daten werden vergleichsweise einfach erzeugt. In den Datagen-Dateien sieht man: Die Spalten entstehen mit kleinen, mittleren und großen Gruppen aus char- und int-Werten. Ähnliche Logik gilt für die Join-Datenerzeugung.

Query SQL Objective
groupby #1 SELECT id1, sum(v1) AS v1 FROM tbl GROUP BY id1 Sum over large cardinality groups, grouped by varchar
groupby #2 SELECT id1, id2, sum(v1) AS v1 FROM tbl GROUP BY id1, id2 Sum over medium cardinality groups, grouped by varchars
groupby #3 SELECT id3, sum(v1) AS v1, mean(v3) AS v3 FROM tbl GROUP BY id3 Sum and mean over many small cardinality groups, grouped by varchar
groupby #4 SELECT id4, mean(v1) AS v1, mean(v2) AS v2, mean(v3) AS v3 FROM tbl GROUP BY id4 Mean over many large cardinality groups, grouped by integer
groupby #5 SELECT id6, sum(v1) AS v1, sum(v2) AS v2, sum(v3) AS v3 FROM tbl GROUP BY id6 Sum over many small groups, grouped by integer
advanced groupby #1 SELECT id4, id5, quantile_cont(v3, 0.5) AS median_v3, stddev(v3) AS sd_v3 FROM tbl GROUP BY id4, id5 quantile_cont over medium cardinality group, grouped by integers
advanced groupby #2 SELECT id3, max(v1)-min(v2) AS range_v1_v2 FROM tbl GROUP BY id3 Range selection over small cardinality groups, grouped by integer
advanced groupby #3 SELECT id6, v3 AS largest2_v3 FROM (SELECT id6, v3, row_number() OVER (PARTITION BY id6 ORDER BY v3 DESC) AS order_v3 FROM x WHERE v3 IS NOT NULL) sub_query WHERE order_v3 <= 2 Advanced group by query
advanced groupby #4 SELECT id2, id4, pow(corr(v1, v2), 2) AS r2 FROM tbl GROUP BY id2, id4 Arithmetic over medium sized groups, grouped by varchar, integer.
advanced groupby #5 SELECT id1, id2, id3, id4, id5, id6, sum(v3) AS v3, count(*) AS count FROM tbl GROUP BY id1, id2, id3, id4, id5, id6 Many small groups, the number of groups is the cardinality of the dataset
join #1 SELECT x.*, small.id4 AS small_id4, v2 FROM x JOIN small USING (id1) Joining a large table (x) with a small-sized table on integer type
join #2 SELECT x.*, medium.id1 AS medium_id1, medium.id4 AS medium_id4, medium.id5 AS medium_id5, v2 FROM x JOIN medium USING (id2) Joining a large table (x) with a medium-sized table on integer type
join #3 SELECT x.*, medium.id1 AS medium_id1, medium.id4 AS medium_id4, medium.id5 AS medium_id5, v2 FROM x LEFT JOIN medium USING (id2) Left join a large table (x) with a medium-sized table on integer type
join #4 SELECT x.*, medium.id1 AS medium_id1, medium.id2 AS medium_id2, medium.id4 AS medium_id4, v2 FROM x JOIN medium USING (id5) Join a large table (x) with a medium table on varchar type
join #5 SELECT x.*, big.id1 AS big_id1, big.id2 AS big_id2, big.id4 AS big_id4, big.id5 AS big_id5, big.id6 AS big_id6, v2 FROM x JOIN big USING (id3) Join a large table (x) with a large table on integer type.

Mehr zu den Abfragen steht in den Folien Efficiency of Data Processing.

Änderungen am Benchmark und an der Hardware

An den Abfragen und an der Datenerzeugung wurde nichts geändert. Einige Skripte brauchten kleine Anpassungen, damit die aktuelle Bibliotheksversion läuft. Die Hardware unterscheidet sich leicht, weil das genaue frühere AWS-Angebot nicht mehr verfügbar ist. Basisbibliotheken wurden ebenfalls aktualisiert. GPU-Bibliotheken wurden nicht getestet.

AWS ist eine Instanz m4.10xlarge:

Änderungen an den Install-Skripten anderer Systeme

Pandas, Polars, Dask und ClickHouse brauchten Änderungen an Setup- bzw. Install-Skripten. Die Änderungen waren vergleichsweise klein: vor allem Syntax-Updates und Anpassungen beim Datenimport. Der Datenimport floss nicht in die berichteten Zeiten ein.

Ergebnisse

Die Ergebnisse können Sie auch direkt ansehen. DuckDBs Zeiten haben sich seit v0.2.7 (vor über zwei Jahren erschienen) deutlich verbessert. Ein großer Beitrag zur höheren Leistung ist die parallele gruppierte Aggregation, gemerged im März 2022, sowie die parallele Materialisierung von Ergebnissets. Außerdem unterstützt DuckDB jetzt Enum-Typen, was GROUP BY-Aggregationen weiter beschleunigt. Auch Verbesserungen am Out-of-Core-Hash-Join wurden gemerged und haben die Join-Leistung weiter verbessert.

Fragen zu einzelnen Ergebnissen?

Manche Lösungen melden bei manchen Abfragen interne Fehler. Sie können die Fehler mit den repro.sh-Skripten nachvollziehen und ein GitHub-Issue öffnen. Außerdem gibt es im Code viele Stellen, an denen bestimmte Abfrageergebnisse automatisch nullifiziert werden. Wenn Sie glauben, dass das auf eine Abfrage Ihres Systems zutrifft, oder wenn Sie andere Fragen haben, können Sie ein GitHub-Issue zur Diskussion anlegen.

Wartungsplan

DuckDB wird diesen Benchmark auf absehbare Zeit weiter pflegen. Der Prozess für erneute Läufe mit aktualisierten Bibliotheksversionen muss noch festgelegt werden.

Haben Sie weitere Fragen? Möchten Sie Ihr System in den Benchmark aufnehmen lassen? Bitte lesen Sie die README im Repository. Wenn danach noch Fragen bleiben, erreichen Sie mich unter tom@ducklabs.com oder auf unserem Discord.