多款OLAP數(shù)據(jù)庫(kù)大比拼,誰(shuí)更勝一籌?
昨天在群里聊到多款OLAP數(shù)據(jù)庫(kù)的性能對(duì)比,想到之前網(wǎng)上找到的一個(gè)benchmark, TPCH_Python_SQL_Engines.ipynb(出處已不可考), 并且為了4月26日的演講,特意在4月24日跑了一遍,這個(gè)是2024年4月24日的對(duì)比結(jié)果。
圖片
圖片
從上面的截圖可以看到, 這里參加評(píng)比的有:
? HyPer:HyPer 是一種高性能、混合事務(wù)和分析處理(HTAP)數(shù)據(jù)庫(kù),專為實(shí)時(shí)數(shù)據(jù)分析和事務(wù)處理而設(shè)計(jì)。
? DuckDB:DuckDB 是一款輕量級(jí)的嵌入式分析數(shù)據(jù)庫(kù),專注于高效處理SQL查詢和分析任務(wù)。
? GlareDB:GlareDB 是一種新型數(shù)據(jù)庫(kù),專注于高性能和擴(kuò)展性,以滿足現(xiàn)代數(shù)據(jù)密集型應(yīng)用的需求。
? Databend(國(guó)產(chǎn)):Databend 是一款國(guó)產(chǎn)云原生數(shù)據(jù)倉(cāng)庫(kù),支持彈性擴(kuò)展和高效的數(shù)據(jù)分析。
? DataFusion:DataFusion 是 Apache Arrow 的一個(gè)子項(xiàng)目,用于構(gòu)建高性能的數(shù)據(jù)處理引擎和分布式 SQL 查詢執(zhí)行。
? CHDB:CHDB 是 ClickHouse 的嵌入式版本,適用于需要在進(jìn)程內(nèi)高效處理列存儲(chǔ)數(shù)據(jù)的場(chǎng)景。
? Apache Spark:Apache Spark 是一個(gè)開源的分布式計(jì)算系統(tǒng),支持大規(guī)模數(shù)據(jù)處理和并行計(jì)算。
本次還將加入
? Polars:Polars 是一個(gè)基于 Rust 的高性能 DataFrame 庫(kù),專為高效的數(shù)據(jù)處理和分析而設(shè)計(jì)。
本次測(cè)試結(jié)果
當(dāng)時(shí)的chdb雖然墊底,但至少還可以跑通
昨天又使用最新版本作了對(duì)比, 這次chdb卡在了Query08和Query09上, 為了確認(rèn)Query09很耗時(shí),我在我的筆記本(mac M2Max 32GB內(nèi)存)上做了測(cè)試,耗時(shí)158s多。
圖片
? chdb的結(jié)果是query08、query09 卡死,放棄后繼續(xù)后面的查詢。08 和09 的結(jié)果比這里看到的數(shù)據(jù)還要糟糕
? 因?yàn)镻olars對(duì)SQL的支持有限, Polars 根據(jù)官方的TPCH[1]做的修改, 另外Query 17的結(jié)果是錯(cuò)誤的,問題放在后面描述。
? 對(duì)比4月份,性能都下降了,難道是Google Colab縮水了?
圖片
圖片
去掉墊底的chdb和pyspark
為了方便比較,去掉了兩個(gè)墊底的:chdb和pyspark
圖片
圖片
Polars的奇怪bug
import pandas as pd
import duckdb
import polars as pl
duckdb.sql("select x, y::decimal(15,2) y from df").to_parquet('decimal.pq')
decimal = pl.scan_parquet('decimal.pq')
? 結(jié)果錯(cuò)誤
pl.sql("""
select x,
avg(y) as avg_y
from decimal
group by 1
""").collect()
圖片
? 這樣OK
# 結(jié)果正確
pl.sql("""
select x,
sum(y) as sum_y
from decimal
group by 1
""").collect()
圖片
? 這樣也可以
pl.sql("""
select x,
sum(y)/count(*) as avg_y
from decimal
group by 1
""").collect()
查找手冊(cè)的時(shí)候發(fā)現(xiàn)。
圖片
好吧, 該類型仍不穩(wěn)定。
優(yōu)雅的代碼
你覺得這樣寫優(yōu)雅。
import pandas as pd
duck_import = pd.read_csv('./result/duckdb.csv')
hyper = pd.read_csv('./result/hyper.csv')
databend = pd.read_csv('./result/databend.csv')
datafusion = pd.read_csv('./result/datafusion.csv')
glaredb = pd.read_csv('./result/glaredb.csv')
chdb = pd.read_csv('./result/chdb.csv')
apachespark = pd.read_csv('./result/apachespark.csv')
polars = pd.read_csv('./result/polars.csv')
concat = duckdb.sql('''select duck_import.query as query,
duck_import.dur as DuckDB , hyper.dur as hyper ,
databend.dur as databend , datafusion.dur as datafusion,
glaredb.dur as glaredb,chdb.dur as chdb,
apachespark.dur as apachespark,ploars.dur as polars
from duck_import
left join hyper
on duck_import.query=hyper.query
left join databend
on duck_import.query=databend.query
left join datafusion
on duck_import.query=datafusion.query
left join glaredb
on duck_import.query=glaredb.query
left join chdb
on duck_import.query=chdb.query
left join apachespark
on duck_import.query=apachespark.query
left join polars
on duck_import.query=polars.query
''').df()
concat
還是這樣寫優(yōu)雅。
import duckdb
concat = duckdb.sql("""
WITH aa AS (
SELECT *
FROM read_csv('result/*.csv', filename=true)
),
bb AS (
SELECT
* EXCLUDE (filename),
REPLACE(REPLACE(filename, '.csv', ''), 'result/', '') AS engine
FROM aa
)
PIVOT bb
ON engine
USING max(dur)
ORDER BY query;
""").df()
concat
以上兩段代碼結(jié)果一樣。
圖片
結(jié)論
從上面的粗淺測(cè)試來(lái)看, 開源的DuckDB和Databend非常值得關(guān)注, Polars對(duì)SQL支持有限,對(duì)Decimal支持有限,入坑請(qǐng)慎重。
Google Colab 到底是不是縮水了?如何驗(yàn)證?