duckdb,单机高效处理海量数据

火山方舟向量数据库大模型

当我们用pandas处理百万级,千万级,乃至上亿行的数据时,缓慢的速度常常让我们痛苦不堪。

这时候,不妨试试duckdb.

duckdb在本地单机即可运行,性能非常高。

它可以像spark那样使用sql语句进行数据分析和数据转换。

当处理几千万行以上的数据时,它的效率通常是pandas的几十几百倍。

公众号算法美食屋后台回复关键词:源码,获取本文notebook源代码。

duckdb个库的用法非常简单,核心API只有以下几个。


      
 

 
  `import duckdb`
 
  `#输入建表:可以从parquet,pandas dataframe建表`
  `tb = duckdb.read_parquet('input_data.parquet')` 
  `tb = duckdb.from_df(df) #从pandas转换`
 
  `#分析转换:执行sql,支持自定义函数UDF`
  `tb2 = duckdb.sql('select * from tb where val>1000 and val<10000 order by val')`
  `duckdb.create_function('myfunc',myfunc,[duckdb.typing.VARCHAR],duckdb.typing.VARCHAR)` 
 
  `#输出落表: 推荐导出成parquet格式,效率最高`
  `tb2.to_parquet('output_data.parquet')`
  `df2 = tb2.to_df() #也可以转换成pandas`
 
 
    

一,输入建表


      
 

 
  `import numpy as np`
  `import pandas as pd`
  `import duckdb`
 
 
    

      
 

 
  `#生成示例数据(5000万行)`
  `dfdemo = pd.DataFrame(`
  `{`
  `'category': np.random.choice(list('ABCDEF'), 50000000),`
  `'val': np.round(np.random.uniform(0, 1000000, 50000000), 3)`
  `}`
  `)`
  `dfdemo.to_parquet('dfdemo.parquet', index=False)`
 
 
    

对比读取数据速度,duckdb比pandas快几十倍

picture.image

二,SQL分析

1, 基本查询

where查询对比 (duckdb比pandas快20倍)

picture.image

groupby 操作对比 (duckdb比pandas快40倍)

picture.image

join 操作对比 (duckdb比pandas快600倍)

picture.image

2,自定义函数UDF

pyspark的一个优点是可以在sql中使用注册自定义函数(UDF),比较灵活。

那么duckdb支持在sql中使用注册自定义函数吗?of course!

⚫️ 注册方法:使用create_function方法来注册一个Python函数作为UDF。需要提供函数名称、Python函数、参数类型和返回类型。

⚫️ 类型注解:如果Python函数有类型注解,可以省略parameters和return_type参数,DuckDB会根据注解自动推断。

⚫️ 空值处理:默认情况下,当UDF接收到NULL值时,会立即返回NULL。如果需要特殊处理,可以设置null_handling="special"。

⚫️ 异常处理:默认情况下,如果Python函数抛出异常,DuckDB会重新抛出该异常。如果希望改为返回null,可以设置exception_handling="return_null"。

⚫️ 副作用:如果UDF的结果受随机性影响,需要将side_effects设置为True。

⚫️ 使用Arrow:如果函数需要接收Arrow数组,设置type='arrow'。这会通知系统提供Arrow数组给函数,并期望函数返回相同数量的数组。

⚫️ 使用Native:当设置type='native'时,函数将按单个元组接收数据,并返回单个值。这适用于与不操作Arrow的Python库交互,如faker。

picture.image


      
 

 
  `import duckdb`
  `from faker import Faker`
  `def generate_random_name(i:int) -> str:` 
  `fake = Faker()`
  `fake.random.seed(i)`
 
  `#演示异常逻辑处理`
  `#if i%10==0:`
  `# raise Exception('error')` 
 
  `name = fake.name()`
  `return name`
 
  `#移除UDF`
  `if 'random_name' in get_rand_funs()['function_name'].tolist():`
  `duckdb.remove_function('random_name')` 
 
 
  `#注册UDF`
  `duckdb.create_function("random_name", generate_random_name,` 
  `[duckdb.typing.BIGINT], duckdb.typing.VARCHAR,` 
  `exception_handling="return_null")`
 
 
    

picture.image

picture.image

三,输出落表


      
 

 
 `tb\_student.to\_parquet('student.parquet')` 
 
 
    

公众号算法美食屋后台回复关键词:源码,获取本文notebook源代码。

万水千山总是情,点个在看行不行?😋😋

picture.image

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
基于 ByteHouse 引擎的增强型数据导入技术实践
ByteHouse 基于自研 HaMergeTree,构建增强型物化 MySQL、HaKafka 引擎,实现数据快速集成,加速业务数据分析性能与效率,本次 talk 主要介绍物化 MySQL 与 HaKafka 数据导入方案和业务实践。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论