58

DuckDB:开篇 - 知乎

 3 years ago
source link: https://zhuanlan.zhihu.com/p/374627729
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

DuckDB:开篇

做数据库的。公众号:coredump


v2-a7da16099389d1a3b751ecc17d9dd11c_720w.png

DuckDB 简介

最近发现了一个适合深入学习的开源分析型数据库——DuckDB。简单说,DuckDB 是一个 OLAP(列存)版本的 SQLite

作为了一个学习样例,DuckDB 具有以下优点:

  1. DuckDB 没有外部依赖,所以编译、链接、运行都可以一气呵成,非常简单。
  2. 代码不算多,除去测试代码,大概 13~14w 行,并且代码质量不错。
  3. 麻雀虽小,五脏俱全。并且 DuckDB 遵循教科书上的经典模块设计,相对容易看懂。
  4. DuckDB 集成了 OLAP 领域的各种知识,它的各种设计、实现都可以找到参考论文,方便学习。

对比 LevelDB

之前也写过一系列 LevelDB 源码解析的文章。 ​

代码量上,LevelDB 大概也就 2w 行,比 DuckDB 少很多。 ​

功能上,LevelDB 只是一个简单的 key-value 存储。而 DuckDB 则是一个完成的数据库——SQL Parser、Optimizer、Execution Engine、Transaction、Storage 一个不少。

DuckDB 的模块介绍

SQL Parser

DuckDB 的 SQL parser 是从 Postgres 的 libpg_query 精简而来的。由于 Postgres 是 C 语言写的,通过这个 SQL parser,我们会得到一个 C 语言结构体表示的 parse tree。DuckDB 会将其转换成自己内部的 C++ 对象。

Logical Planner

Logical planner 由 binder 和 plan generator 两部分组成。 Binder 将 parse tree 与 schema 的信息(列名、类型等)绑定起来。Schema 信息保存在 catalog。 Plan generator 将 parse tree 转换成一颗逻辑查询操作符(scan, filter, project 等)树。

Optimizer

DuckDB 实现了基于规则(rule-based)和基于代价(cost-based)的优化器。Optimizer 的主要任务是优化 SQL,它将前面 logical planner 生成的 logical plan 转换成一个等价但执行代价更小的 logical plan。常见的优化方式有谓词下推(predicate pushdown)、表达式重写(expression rewriting)、调整 join 顺序(join ordering)等。

Physical Planner 和 Execution Engine

Physical planner 和 execution engine 的代码都在 execution 目录下。 Physical planner 将 Logical plan 转换成 physical plan。Physical plan 是一个真正可以执行的物理计划。 DuckDB 实现了一个向量化(vectorized)的解释型执行引擎。 向量化可以利用 CPU 提供的 SIMD 指令加速计算。DuckDB 采用 SQL 的解释执行,而没有采用 SQL 的编译执行,原因是编译执行需要依赖编译组件,比如 LLVM,这会导致 DuckDB 的体积膨胀不少。

Transaction and Concurrency Control

DuckDB 支持 Serializable 的事务隔离。事务相关的代码在 transaction 目录下。

Storage

Storage 是 DuckDB 的列式存储引擎,处于整个 DuckDB 架构的最底层,负责提供数据的高效读写。

编译运行

DuckDB 的下载和编译很简单:

git clone https://github.com/duckdb/duckdb
cd duckdb
BUILD_BENCHMARK=1 BUILD_TPCH=1 make

编译完成后,我们可以得到一个 DuckDB 的二进制库+头文件。另外,我们得到一个 benchmark 程序,可以用来测试 DuckDB 的性能。

# 列出所支持的 benchmark 
build/release/benchmark/benchmark_runner --list

# 运行指定的一个 benchmark
build/release/benchmark/benchmark_runner benchmark/tpch/sf1/q01.benchmark

# 运行某个目录下的 benchmark
build/release/benchmark/benchmark_runner 'benchmark/tpch/sf1/.*'

# 运行所有 benchmark
build/release/benchmark/benchmark_runner

关于 benchmark_runner 的更多功能,可以参考官方文档


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK