1.1 OLTP vs OLAP:两种不同的数据库世界
数据库按工作负载可以分为两大类,它们的设计目标截然不同:
| 维度 | OLTP(联机事务处理) | OLAP(联机分析处理) |
|---|---|---|
| 全称 | On-Line Transaction Processing | On-Line Analytical Processing |
| 典型操作 | INSERT / UPDATE / DELETE 单行 | SELECT 聚合大量行 |
| 数据量 | 通常 MB ~ GB | GB ~ TB 甚至 PB |
| 查询特点 | 简单点查,毫秒级响应 | 复杂聚合,扫描大量列 |
| 存储方式 | 行式存储(Row-oriented) | 列式存储(Column-oriented) |
| 代表数据库 | MySQL、PostgreSQL、SQLite | DuckDB、ClickHouse、BigQuery、Snowflake |
| 典型用途 | 电商下单、用户登录、支付流水 | 销售报表、用户行为分析、BI 看板 |
DuckDB 的定位 DuckDB 是一个嵌入式 OLAP 数据库。它专门针对分析查询(读多写少、大范围聚合)优化,而不是 OLTP(高频单行事务)。把它理解为"分析领域的 SQLite"非常贴切。
1.2 SQLite 的对比:行存 vs 列存
SQLite 是最著名的嵌入式数据库,DuckDB 在很多方面借鉴了 SQLite 的设计哲学(无服务进程、单文件),但在存储引擎上做了根本性的不同选择。
行式存储(SQLite/MySQL) 一行数据的所有列存放在一起。读取某行很快,但分析查询(如 SUM(sales) 跨 100 万行)必须读取整行,浪费大量 I/O 在无关列上。
列式存储(DuckDB/ClickHouse) 同一列的所有值连续存放。分析查询只需读取目标列,I/O 减少 10~100 倍;同列数据类型相同,压缩率极高(ZSTD/Snappy)。
直观示意:查询 SUM(amount)
假设有 100 万行订单数据,每行包含 order_id、user_id、product、amount、created_at 5 列:
| 存储方式 | 需要读取的数据 | I/O 量 | 速度 |
|---|---|---|---|
| 行式(MySQL) | 所有 5 列 × 100万行 | ~500 MB | 慢 |
| 列式(DuckDB) | 仅 amount 列 × 100万行 | ~8 MB(压缩后) | 极快 |
1.3 DuckDB 的核心优势
- 零依赖部署 不需要单独的服务器进程,不需要 Docker,不需要配置文件。pip install duckdb 或下载单个二进制文件即可使用。
- 直接查询文件 可以直接 SELECT * FROM 'data.csv' 而无需先导入数据库。支持 CSV、Parquet、JSON、ORC、Arrow 格式。
- 向量化执行引擎 CPU 每次处理一批数据(默认 2048 行),充分利用 SIMD 指令集,CPU 缓存命中率极高,分析速度远超传统数据库。
- Python 零拷贝集成 直接操作 pandas/polars DataFrame,数据不需要在 Python 和 DuckDB 之间复制。可以在 SQL 中直接引用 Python 变量。
- 标准 SQL 兼容 支持完整的 SQL 标准,包括窗口函数、CTE、LATERAL JOIN 等高级特性,还扩展了 PIVOT、QUALIFY、ASOF JOIN 等分析专用语法。
- 超内存数据处理 当数据量超过内存时,DuckDB 会自动将中间结果溢写到磁盘(Spilling),仍然可以处理比内存大得多的数据集。
1.4 DuckDB 适用场景
本地数据分析
直接查询本地 CSV/Parquet 文件,比 pandas 快 10-100 倍,比启动 Spark 集群方便 100 倍。
ETL / ELT 管道
构建本地数据转换管道,与 dbt 配合,无需云数仓也能完成复杂的数据转换工作。
文件格式转换
CSV → Parquet、JSON → Parquet,一条 SQL 完成,自动推断 Schema,处理大文件毫无压力。
数据探索
在 Jupyter Notebook 中快速探索数据,ad-hoc 查询比 pandas 更直观、更快。
S3 文件直查
通过 httpfs 扩展,直接查询 S3/GCS/Azure Blob 上的文件,无需下载到本地。
数仓本地开发
用 dbt + DuckDB 在本地开发和测试数据模型,不花一分钱云费用,推送到生产再切换到 Snowflake/BigQuery。
不适合的场景 DuckDB 不适合高并发 OLTP(高频单行写入)、多客户端并发写入(它是嵌入式数据库,写并发有限)、以及需要复杂行级权限控制的企业系统。这些场景请用 PostgreSQL 或 MySQL。
1.5 安装:多种方式任选
CLI(命令行工具)
BASH# macOS (Homebrew)
brew install duckdb
# 直接下载二进制(所有平台)
# 访问 https://duckdb.org/docs/installation/ 下载对应平台版本
# macOS Apple Silicon
curl -LO https://github.com/duckdb/duckdb/releases/latest/download/duckdb_cli-osx-universal.zip
unzip duckdb_cli-osx-universal.zip
./duckdb
# Linux
curl -LO https://github.com/duckdb/duckdb/releases/latest/download/duckdb_cli-linux-amd64.zip
unzip duckdb_cli-linux-amd64.zip
./duckdb
Python
BASH# Python 3.7+
pip install duckdb
# 或 uv(更快)
uv pip install duckdb
# 验证安装
python -c "import duckdb; print(duckdb.__version__)"
Node.js
BASH# npm
npm install duckdb
# 或更现代的 @duckdb/node-api
npm install @duckdb/node-api
R
R# R 控制台内安装
install.packages("duckdb")
library(duckdb)
con <- dbConnect(duckdb())
dbGetQuery(con, "SELECT 42")
Java / JVM
XML<!-- Maven -->
<dependency>
<groupId>org.duckdb</groupId>
<artifactId>duckdb_jdbc</artifactId>
<version>1.1.3</version>
</dependency>
1.6 第一个查询:直接读 CSV 文件
DuckDB 最令人兴奋的特性之一:直接查询 CSV 文件,不需要先建表、不需要导入数据。
准备测试数据
BASH# 创建一个示例 CSV 文件
cat > sales.csv <<EOF
date,region,product,amount
2024-01-01,华北,笔记本,8999
2024-01-01,华南,手机,3999
2024-01-02,华北,平板,4999
2024-01-02,华东,笔记本,8999
2024-01-03,华南,手机,3999
2024-01-03,华东,平板,4999
EOF
DuckDB CLI 中直接查询
SQL-- 启动 DuckDB CLI(不带参数=内存模式)
duckdb
-- 直接 SELECT CSV 文件!
SELECT * FROM 'sales.csv';
-- 按地区聚合销售额
SELECT
region,
SUM(amount) AS total_sales,
COUNT(*) AS order_count
FROM 'sales.csv'
GROUP BY region
ORDER BY total_sales DESC;
Python 中使用
PYTHONimport duckdb
# 执行查询并获取结果(返回 list of tuples)
result = duckdb.sql("SELECT * FROM 'sales.csv'").fetchall()
print(result)
# 返回 pandas DataFrame
df = duckdb.sql("""
SELECT region, SUM(amount) as total
FROM 'sales.csv'
GROUP BY region
ORDER BY total DESC
""").df()
print(df)
1.7 名词解释:核心概念
- 列式存储 将同一列的所有值连续存储在磁盘上,而不是按行存储。分析查询只读取需要的列,大幅减少 I/O;同列数据类型一致,压缩效果极佳(通常 5-10倍压缩比)。
- 向量化执行 CPU 每次处理一个"向量"(batch,默认 2048 行)而不是逐行处理。可以充分利用 CPU 的 SIMD(Single Instruction Multiple Data)指令,一条 CPU 指令同时处理 8/16/32 个数值,效率提升数倍。
- OLAP On-Line Analytical Processing,联机分析处理。特点:查询复杂(多表 JOIN、大量聚合),数据量大,读多写少,对延迟要求不如 OLTP 严格,但吞吐量要求高。
- 嵌入式数据库 数据库引擎作为库直接嵌入应用进程中运行,不需要独立的服务器进程。优点:部署简单、无网络延迟、无进程通信开销。代表:SQLite(OLTP)、DuckDB(OLAP)。
- Zone Maps 列式存储的元数据统计信息:记录每个数据块的 min/max 值。查询时可以跳过不满足条件的数据块(谓词下推),大幅减少实际读取的数据量。
- 进程内数据库 In-process database,与嵌入式数据库含义相近。数据库在调用者的进程内运行,共享内存空间,可以零拷贝访问 Python 对象(如 pandas DataFrame)。
本章小结 DuckDB 是嵌入式 OLAP 数据库,无服务进程,像 SQLite 一样易部署,但专为分析查询优化。列式存储 + 向量化执行是其高性能的根本。适合本地数据分析、ETL、文件查询,不适合高并发 OLTP。一行 pip install duckdb 即可上手,可直接 SELECT CSV/Parquet 文件,与 pandas 深度集成。