duckdb 在 python 中做本地 olap 分析最省事的起点是直接调用 duckdb.sql(),它自动使用内存数据库、执行完即丢,适合探索性查询;需用 con.register() 将 pandas dataframe 注册为虚拟表以实现零拷贝查询;读 parquet/csv 推荐直接在 sql 中引用文件路径;避免函数包装列、前导通配符 like 和类型不一致 join 以防退化为行式扫描。

直接用 duckdb.sql() 就能开干,不用 connect、不用建库、不用启服务——这是 DuckDB 在 Python 里做本地 OLAP 分析最省事的起点。
用 duckdb.sql() 快速执行一次性查询
多数轻量分析场景根本不需要显式创建连接对象。DuckDB 提供顶层函数 duckdb.sql(),它自动使用内存数据库,执行完即丢,适合探索性查询或单次聚合。
- 常见错误:写成
duckdb.execute("SELECT ...")——这个方法不存在,会报AttributeError - 正确写法是
duckdb.sql("SELECT ..."),返回一个duckdb.DuckDBPyRelation对象 - 想转成 Pandas DataFrame?调
.fetchdf();要取原始元组列表?用.fetchall() - 注意:
duckdb.sql()不共享状态,连续两次调用互不影响,无法跨语句复用表名(除非注册)
示例:
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
import duckdb
result = duckdb.sql("SELECT SUM(x) FROM (VALUES (1), (2), (3)) AS t(x)")
print(result.fetchdf()) # sum_1
# 0 6
用 con.register() 把 Pandas DataFrame 当成 SQL 表查
这是 DuckDB 和 pandas 协同最自然的方式:不导出、不序列化、零拷贝(实际是引用+元数据映射),DataFrame 直接变成可 SQL 查询的“虚拟表”。
- 必须先调
con.register("table_name", df),之后才能在 SQL 中用FROM table_name - 注册后修改原 DataFrame 的值,查询结果会同步变化(因为是视图式引用)
- 别用
con.execute("CREATE TABLE ... AS SELECT ...")去“持久化” DataFrame——那会触发完整拷贝,失去性能优势 - 如果 DataFrame 含时区感知 datetime(
datetime64[ns, UTC]),DuckDB 会自动识别并支持TIMESTAMP WITH TIME ZONE运算
示例:
import pandas as pd
import duckdb
<p>df = pd.DataFrame({"x": [1, 2, 3], "cat": ["a", "b", "a"]})
con = duckdb.connect()
con.register("mydf", df)
result = con.sql("SELECT cat, SUM(x) FROM mydf GROUP BY cat").fetchdf()</p>
读 Parquet/CSV 文件时,别手动 read_csv_auto(),优先用文件路径直查
DuckDB 支持在 SQL 中直接引用外部文件路径,底层自动调用 read_parquet() 或 read_csv_auto(),省去显式加载步骤,也避免中间 DataFrame 占内存。
- 写法就是
SELECT * FROM 'data.parquet'或SELECT * FROM read_csv_auto('data.csv') - 推荐前者:DuckDB 能推断 Parquet schema,跳过类型扫描;而
read_csv_auto()首次需采样,可能误判列类型(比如把全数字 ID 当成 INT,实际应为 VARCHAR) - 大 CSV 没索引?加
sample_size=20000参数提升类型推断准确率:read_csv_auto('log.csv', sample_size=20000) - Parquet 文件带分区(如
dt=2025-01-01/子目录)?直接查父目录,DuckDB 自动识别 Hive-style 分区
示例:
# 查整个分区目录(自动识别 dt=... 子目录)
duckdb.sql("SELECT COUNT(*) FROM 's3://bucket/logs/' WHERE dt >= '2026-08-01'")
<h1>本地多 Parquet 文件合并查</h1><p>duckdb.sql("SELECT <em> FROM '</em>.parquet'")</p>
聚合慢?检查是否意外触发了行式扫描
DuckDB 默认按列式执行,但某些写法会让优化器退化到逐行处理,典型表现是 CPU 占满、内存暴涨、速度不如 pandas。
- 避免在
WHERE或JOIN条件中对列做函数包装,比如WHERE UPPER(name) = 'JOHN'——改用WHERE name ILIKE 'john' - 别用
LIKE '%abc'前导通配符,DuckDB 无法走字典跳过,会全扫;真要前缀匹配,建CREATE INDEX ON tbl(name) - JOIN 大表时,确保关联字段类型一致:
INT和BIGINT强制隐式转换会阻断向量化 - 用
EXPLAIN SELECT ...看执行计划,重点找有没有SEQUENTIAL SCAN或UNNEST类低效节点
真正影响性能的往往不是数据量,而是你写的那一行 SQL 是否让 DuckDB “看懂了你想干嘛”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










