四种python工具包用SQL查询csv和parquet文件的方法比较

  1. chdb
sql 复制代码
root@kylin-pc:/# python3
Python 3.14.3 (main, Feb 24 2026, 22:48:09) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import chdb
>>> chdb.sql("select sum(l_quantity) from file('/par/lineitem.parquet')")
1529738036

>>> chdb.sql("select sum(l_quantity) from file('/par/lineitem.csv')")
1529738036

>>> import duckdb
>>> duckdb.sql("select sum(l_quantity) from '/par/lineitem.parquet'")
┌─────────────────┐
│ sum(l_quantity) │
│  decimal(38,2)  │
├─────────────────┤
│   1529738036.00 │
└─────────────────┘

>>> duckdb.sql("select sum(l_quantity) from '/par/lineitem.csv'")
100% ▕██████████████████████████████████████▏ (00:00:06.93 elapsed)     
┌─────────────────┐
│ sum(l_quantity) │
│     double      │
├─────────────────┤
│    1529738036.0 │
└─────────────────┘
  1. polars
sql 复制代码
>>> import polars as pl

>>> df=pl.read_csv("/par/lineitem.csv", separator=",")
>>> ctx = pl.SQLContext(my_table=df, eager=True)
>>> result = ctx.execute("select sum(l_quantity) from my_table")
>>> print(result)
shape: (1, 1)
┌────────────┐
│ l_quantity │
│ ---        │
│ f64        │
╞════════════╡
│ 1.5297e9   │
└────────────┘

>>> df=pl.read_parquet("/par/lineitem.parquet")
>>> ctx = pl.SQLContext(my_table=df, eager=True)
>>> result = ctx.execute("select sum(l_quantity) from my_table")
>>> print(result)
shape: (1, 1)
┌───────────────┐
│ l_quantity    │
│ ---           │
│ decimal[15,2] │
╞═══════════════╡
│ 1529738036.00 │
└───────────────┘
  1. datafusion
sql 复制代码
>>> from datafusion import SessionContext
>>> ctx = SessionContext()


>>> ctx.register_csv("lineitem", "/par/lineitem.csv")
>>> ctx.sql("select sum(l_quantity) from lineitem")
DataFrame()
+--------------------------+
| sum(lineitem.l_quantity) |
+--------------------------+
| 1529738036.0             |
+--------------------------+
>>> ctx.register_parquet("lineitem2", "/par/lineitem.parquet")
>>> ctx.sql("select sum(l_quantity) from lineitem2")
DataFrame()
+---------------------------+
| sum(lineitem2.l_quantity) |
+---------------------------+
| 1529738036.00             |
+---------------------------+
  1. databend
sql 复制代码
>>> import databend
>>> ctx = databend.SessionContext()
>>> ctx.register_csv("lineitem", "/par/lineitem.csv")
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    ctx.register_csv("lineitem", "/par/lineitem.csv")
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: DataFrame collect error: SemanticError. Code: 1065, Text = [QUERY-CTX] Query from CSV file lacks column positions. Specify as $1, $2, etc..

<Backtrace disabled by default. Please use RUST_BACKTRACE=1 to enable> 
>>> ctx.register_parquet("lineitem2", "/par/lineitem.parquet")
>>> ctx.sql("select sum(l_quantity) from lineitem2")
┌─────────────────────┐
│   sum(l_quantity)   │
│ Decimal(18, 2) NULL │
├─────────────────────┤
│ 1529738036.00       │
└─────────────────────┘

databend的register_csv方式据开发人员说准备废弃了。

  1. 对100万行数据group by的性能比较

    root@kylin-pc:/# time python /par/test_duck2.py
    ┌───────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
    │ a │ b0 │ b1 │ b2 │ b3 │ b4 │ b5 │ b6 │
    │ int64 │ int64 │ int64 │ int64 │ int64 │ int64 │ int64 │ int64 │
    ├───────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
    │ 0 │ 714286 │ 714286 │ 714286 │ 714285 │ 714286 │ 714285 │ 714286 │
    │ 1 │ 714286 │ 714286 │ 714286 │ 714286 │ 714285 │ 714286 │ 714285 │
    └───────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘

    0.09658598899841309
    ┌───────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
    │ a │ b0 │ b1 │ b2 │ b3 │ b4 │ b5 │ b6 │
    │ int64 │ int128 │ int128 │ int128 │ int128 │ int128 │ int128 │ int128 │
    ├───────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
    │ 0 │ 714286 │ 714286 │ 714286 │ 714285 │ 714286 │ 714285 │ 714286 │
    │ 1 │ 714286 │ 714286 │ 714286 │ 714286 │ 714285 │ 714286 │ 714285 │
    └───────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘

    0.01613473892211914

    real 0m0.868s
    user 0m2.157s
    sys 0m0.181s

    root@kylin-pc:/# time python /par/test_ch2.py
    0,714286,714286,714286,714285,714286,714285,714286
    1,714286,714286,714286,714286,714285,714286,714285

    0.23157906532287598
    0,714286,714286,714286,714285,714286,714285,714286
    1,714286,714286,714286,714286,714285,714286,714285

    0.05921816825866699

    real 0m0.694s
    user 0m2.803s
    sys 0m0.814s

    root@kylin-pc:/# time python /par/test_pl.py
    shape: (2, 8)
    ┌─────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
    │ a ┆ b0 ┆ b1 ┆ b2 ┆ b3 ┆ b4 ┆ b5 ┆ b6 │
    │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
    │ i64 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 │
    ╞═════╪════════╪════════╪════════╪════════╪════════╪════════╪════════╡
    │ 0 ┆ 714286 ┆ 714286 ┆ 714286 ┆ 714285 ┆ 714286 ┆ 714285 ┆ 714286 │
    │ 1 ┆ 714286 ┆ 714286 ┆ 714286 ┆ 714286 ┆ 714285 ┆ 714286 ┆ 714285 │
    └─────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
    0.15063023567199707
    shape: (2, 8)
    ┌─────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
    │ a ┆ b0 ┆ b1 ┆ b2 ┆ b3 ┆ b4 ┆ b5 ┆ b6 │
    │ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
    │ i64 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 │
    ╞═════╪════════╪════════╪════════╪════════╪════════╪════════╪════════╡
    │ 1 ┆ 714286 ┆ 714286 ┆ 714286 ┆ 714286 ┆ 714285 ┆ 714286 ┆ 714285 │
    │ 0 ┆ 714286 ┆ 714286 ┆ 714286 ┆ 714285 ┆ 714286 ┆ 714285 ┆ 714286 │
    └─────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
    0.11575460433959961

    real 0m1.090s
    user 0m1.985s
    sys 0m0.454s

test_duck2.py

python 复制代码
import duckdb


conn = duckdb.connect(":memory:")

conn.query("create table t as select i%2 a, i%7 b,i%11 c from range(10000000)t(i)")


s1="""
select a,
count(case b when 0 then 1 end)b0 , 
count(case b when 1 then 1 end)b1 , 
count(case b when 2 then 1 end)b2 , 
count(case b when 3 then 1 end)b3 , 
count(case b when 4 then 1 end)b4 , 
count(case b when 5 then 1 end)b5 ,
count(case b when 6 then 1 end)b6  
from t group by a;
"""

s2="""
with t1 as(select count(*)cnt ,a,b from t group by a,b)
select a,
sum(case b when 0 then cnt end)b0 , 
sum(case b when 1 then cnt end)b1 , 
sum(case b when 2 then cnt end)b2 , 
sum(case b when 3 then cnt end)b3 , 
sum(case b when 4 then cnt end)b4 , 
sum(case b when 5 then cnt end)b5 ,
sum(case b when 6 then cnt end)b6  
from t1 group by a;
"""

import time
t=time.time()
res =conn.query(s1)
print(res)
print(time.time()-t)

t=time.time()
res =conn.query(s2)
print(res)
print(time.time()-t)

test_ch2.py

python 复制代码
import chdb


conn = chdb.connect(":memory:")

conn.query("create table t as select i%2 a, i%7 b,i%11 c from (select number i from numbers(10000000))")


s1="""
select a,
count(case b when 0 then 1 end)b0 , 
count(case b when 1 then 1 end)b1 , 
count(case b when 2 then 1 end)b2 , 
count(case b when 3 then 1 end)b3 , 
count(case b when 4 then 1 end)b4 , 
count(case b when 5 then 1 end)b5 ,
count(case b when 6 then 1 end)b6  
from t group by a;
"""

s2="""
with t1 as(select count(*)cnt ,a,b from t group by a,b)
select a,
sum(case b when 0 then cnt end)b0 , 
sum(case b when 1 then cnt end)b1 , 
sum(case b when 2 then cnt end)b2 , 
sum(case b when 3 then cnt end)b3 , 
sum(case b when 4 then cnt end)b4 , 
sum(case b when 5 then cnt end)b5 ,
sum(case b when 6 then cnt end)b6  
from t1 group by a;
"""

import time
t=time.time()
res =conn.query(s1)
print(res)
print(time.time()-t)

t=time.time()
res =conn.query(s2)
print(res)
print(time.time()-t)

test_pl.py

python 复制代码
import polars as pl
data = {"i": [i for i in range(10000000)]}
df = pl.LazyFrame(data)

ctx = pl.SQLContext(my_table=df, eager=True)

result = ctx.execute("create table t as select i%2 a, i%7 b,i%11 c from my_table")


s1="""
select a,
count(case b when 0 then 1 end)b0 , 
count(case b when 1 then 1 end)b1 , 
count(case b when 2 then 1 end)b2 , 
count(case b when 3 then 1 end)b3 , 
count(case b when 4 then 1 end)b4 , 
count(case b when 5 then 1 end)b5 ,
count(case b when 6 then 1 end)b6  
from t group by a;
"""

s2="""
with t1 as(select count(*)cnt ,a,b from t group by a,b)
select a,
sum(case b when 0 then cnt end)b0 , 
sum(case b when 1 then cnt end)b1 , 
sum(case b when 2 then cnt end)b2 , 
sum(case b when 3 then cnt end)b3 , 
sum(case b when 4 then cnt end)b4 , 
sum(case b when 5 then cnt end)b5 ,
sum(case b when 6 then cnt end)b6  
from t1 group by a;
"""

import time
t=time.time()
res =ctx.execute(s1)
print(res)
print(time.time()-t)

t=time.time()
res =ctx.execute(s2)
print(res)
print(time.time()-t)

注意有的工具是惰性的,print()函数不能保证各参数的执行顺序,导致出现奇怪的计时结果。所以不能简写为

复制代码
t=time.time()
res =conn.query(s1)
print(res,time.time()-t)

┌───────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│   a   │   b0   │   b1   │   b2   │   b3   │   b4   │   b5   │   b6   │
│ int64 │ int64  │ int64  │ int64  │ int64  │ int64  │ int64  │ int64  │
├───────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│     0 │ 714286 │ 714286 │ 714286 │ 714285 │ 714286 │ 714285 │ 714286 │
│     1 │ 714286 │ 714286 │ 714286 │ 714286 │ 714285 │ 714286 │ 714285 │
└───────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
 0.0005764961242675781
相关推荐
阿里云大数据AI技术14 小时前
Hologres AI Function 文本分类实战:从提示词设计到 KV-Cache 调优,全程 SQL 搞定
人工智能·sql
Lyn_Li14 小时前
扫描 PDF 歪了怎么办?用 6 种检测方法做本地批量扶正(附开源工具)
python·pdf·ocr·tesseract·开源工具·文档处理·本地处理·扫描件纠偏
金銀銅鐵15 小时前
费马小定理
python·数学·算法
code_pgf15 小时前
AI-Agent记忆机制分析
大数据·人工智能
cc57250265318 小时前
挑选大数据专业院校,重点参考哪几项指标
大数据
疋瓞19 小时前
python和C++对比(1)_数据类型和数据结构
数据结构·c++·python
2601_9626838919 小时前
治理遗留系统中的“生肉 SQL”:一次用多模型协作优化慢查询的实战复盘
数据库·人工智能·sql
如此这般英俊20 小时前
手搓Claude Code-第六章 subagent
数据结构·人工智能·python·语言模型·自然语言处理
shushangyun_21 小时前
2026智能采购商城系统选型指南:如何引领企业数字化采购升级
java·大数据·数据库·人工智能·机器学习
元Y亨H21 小时前
Python - FastAPI 全方位介绍
python·fastapi