⌘+k ctrl+k
1.4 (LTS)
搜索快捷键 cmd + k | ctrl + k
基准测试套件

DuckDB 拥有一个广泛的基准测试套件。当进行可能影响性能的更改时,运行这些基准测试以检测潜在的性能退化非常重要。

入门

要构建基准测试套件,请在 DuckDB 代码仓库中运行以下命令

BUILD_BENCHMARK=1 BUILD_EXTENSIONS='tpch' make

列出基准测试

要列出所有可用的基准测试,请运行

build/release/benchmark/benchmark_runner --list

运行基准测试

运行单个基准测试

要运行单个基准测试,请执行以下命令

build/release/benchmark/benchmark_runner benchmark/micro/nulls/no_nulls_addition.benchmark

输出将以 CSV 格式打印到 stdout,格式如下

name	run	timing
benchmark/micro/nulls/no_nulls_addition.benchmark	1	0.121234
benchmark/micro/nulls/no_nulls_addition.benchmark	2	0.121702
benchmark/micro/nulls/no_nulls_addition.benchmark	3	0.122948
benchmark/micro/nulls/no_nulls_addition.benchmark	4	0.122534
benchmark/micro/nulls/no_nulls_addition.benchmark	5	0.124102

您还可以使用 --out 标志指定输出文件。这将仅把计时结果(以换行符分隔)写入该文件。

build/release/benchmark/benchmark_runner benchmark/micro/nulls/no_nulls_addition.benchmark --out=timings.out

输出将包含以下内容

0.182472
0.185027
0.184163
0.185281
0.182948

使用正则表达式运行多个基准测试

您也可以使用正则表达式来指定要运行哪些基准测试。请注意 shell 对某些正则字符的扩展(例如,* 很可能会被您的 shell 扩展,因此需要正确引用或转义)。

build/release/benchmark/benchmark_runner "benchmark/micro/nulls/.*"

运行所有基准测试

不指定任何参数将运行所有基准测试。

build/release/benchmark/benchmark_runner

其他选项

--info 标志为您提供有关基准测试的其他一些信息。

build/release/benchmark/benchmark_runner benchmark/micro/nulls/no_nulls_addition.benchmark --info
display_name:NULL Addition (no nulls)
group:micro
subgroup:nulls

--query 标志将打印基准测试所运行的查询。

SELECT min(i + 1) FROM integers;

--profile 标志将输出查询树。

创建基准测试

一些开发工作围绕性能展开,在其他测试中加入基准测试不仅可以验证改进,还可以防止未来功能开发中出现性能退化。

基准测试示例

为了说明如何创建基准测试文件,我们可以查看 FILL 窗口函数的基准测试。(FILL 函数用于对有序分区中的缺失值进行线性插值。)

基准测试类似于单元测试文件,并且具有相同类型的标题。

# name: benchmark/micro/window/window_fill.benchmark
# description: Measure the performance of FILL
# group: [window]

make format-head 命令可以确保标题具有预期的结构并防止 tidy 检查错误。

在此标题下方,有一组总结该基准测试的关键字。

name FillPerformance
group micro
subgroup window

虽然有些基准测试运行单个查询,但使用 argument 关键字来参数化基准测试通常很有用。这允许在不同的设置(如数据量)下运行基准测试。对于 FILL 基准测试,有三个参数

argument sf 10
argument errors 0.1
argument keys 4

对于 FILL,这些参数是

  • 比例因子(每个分区的百万行数)
  • 错误率(缺失值所占的比例)
  • 分区数量。

基准测试通常需要在运行查询之前进行一些数据准备。数据准备在基准测试文件的 load 部分完成。对于 FILL 基准测试,我们使用这些参数和一个随机数生成器创建一个表。

load
select setseed(0.8675309);
create or replace table data as (
	select
		k::TINYINT as k,
		(case when random() > ${errors} then m - 1704067200000 else null end) as v,
		m,
	from range(1704067200000, 1704067200000 + ${sf} * 1_000_000 * 10, 10) times(m)
	cross join range(${keys}) keys(k)
);

argument 参数会在查询中展开,类似于单元测试中 foreach 值的展开方式。请注意,我们可以在 load 部分执行多个 SQL 语句。

数据准备好后,我们终于可以指定要进行基准测试的查询了!这在 run 部分完成,限制与单元测试相同(例如,没有空行等)。对于 FILL 基准测试,我们想要找出所有插值失败的地方

run
SELECT
	m,
	k,
	fill(v) OVER (PARTITION BY k ORDER BY m) as v
FROM
	data
qualify v <> m - 1704067200000;

如果插值正确,无论规模如何,我们都不会有任何输出。我们可以通过最终的 result 子句来检查这一点,该子句与单元测试具有相同的语法

result III

通过提供空输出行,我们既可以检查查询的正确性,也可以检查其性能。

在顶级的 benchmark/ 目录中还有许多其他示例,您不妨看看以探索其他技术。

© 2025 DuckDB 基金会,阿姆斯特丹,荷兰
行为准则 商标使用指南