DuckDB功能点介绍

目录

前阵子浏览技术文章不经意间看到DuckDB,文章将它描述成为OLAP版本的SQLite,或嵌入式的PgSQL,有众多现代化分析型数据库的高级功能,支持众多API,在python API中还可以不用copy直接用SQL查询Pandas DataFrame。用了几天后发现惊喜有点多,特写此文章进行记录,方便日后查阅。

本文主要介绍DuckDB对本人日常工作有用的功能点,不做太多展开,官方文档才是最全面和详细的。
以后如果再写DuckDB相关的博客,主题将为具体应用案例分享。

安装与简单配置

pip install duckdb之后就可直接在python中使用,也可以下载JDBC Driver然后配置在DBeaver等支持JDBC的数据库管理工具中使用。 既可以连接本地数据库(仅需提供一个path)后使用,也可直接在in memory模式下使用。

免导入,直接查询数据文件

可直接查询csv,parquet,json,excel等文件。 以csv和parquet为例,可分别通过read_csv和read_parquet函数查询,若无需额外的参数控制,甚至可以免去函数名。

-- csv
select * from 'file.csv'
select * from read_csv('file.csv',delim='|', nullstr='NA', ....)

-- parquet
select * from '/file.parquet' 
select * from read_parquet('file.parquet',hive_partitioning=true, ....) 

csv不自带元数据信息,但duckdb支持以一定的算法推测/嗅探CSV元数据:

select * from sniff_csv('file.csv')

parquet一般自带元数据,可直接读取:

-- self contained metadata in parquet file
select * from parquet_metadata('test.parquet');
select * from parquet_schema('test.parquet')

-- data schema
describe select * from read_parquet('file.parquet')

将query结果导出为各种常见文件格式也非常方便,详情见文档

免copy,查询dataframe

目前dataframe已经成为了数据处理和分析最流行的数据结构,duckdb在python中可以用SQL高效率地查询pandas dataframe,实现SQL与dataframe API的无缝集成和优势互补。

用一例子简单说明:

import pandas as pd
import duckdb

df_diamond = pd.read_csv(r'/data/diamondsbig.csv')
duckdb.sql('''
    select *
        , list_max([x,y,z]) as max_xyz
        , count(distinct color) over(partition by cut) as color_cnt_by_cut
    from df_diamond
''')

对dataframe模拟SQL中的窗口函数是比较复杂且在大数据量的情况下是无法保证性能的,但借助SQL,一切都都变得简单。
除了pandas dataframe,duckdb同样支持零拷贝直接查询Apache arrow tablePolars dataframe

功能丰富

  • 丰富的自带函数库
  • 支持复杂数据类型,比如list,struct, map,array,以及这些类型相关的函数
    • 像python一样的range generate…,list slice,list comprehension等,非常适合基于大宽表在同一row中的多个column之间进行数据处理和分析,比如同一行基于某几列的值计算hash值,最大值,最小值等
  • 支持用python写UDF

简洁和友好的SQL语法

  • column alias in where/group by/having
  • group by all
  • dynamic columns
  • incremental column alias in select
  • windows function having clasue

更多友好语法见官方博客:

PgSQL式用法

duckdb是用了pgsql的SQL引擎,支持大量pgSQL方言,比如:

select <table_name> from <table_name>
::做数据转换

drop table if exists table_test;
create table table_test as
    select 1 as id , 'a' as title, 'xxx' as remark union all
    select 2 , 'b','yyy' union all
    select 3, 'c', 'zzz';

select a as _struct, a::text as str from table_test a;
select row(id,title) as xrow, xrow::text from table_test a; 

其它相关有用库

其它数据分析与处理相关的弹药库:

  • polars(在单机有限内存的情况下,更高性能的dataframe)
  • ibis ( 在dataframe和SQL之间统一API,一套代码多套backend,方便迁移 )
  • sqlglot ( SQL解析,SQL方言转换<比如T-SQL转为Hive SQL等>,日常还可用来做血缘关系分析 )