pg_duckdb性能测试:TPC-H基准下的OLAP能力突破
你是否还在为PostgreSQL在大规模数据分析场景下的性能瓶颈而困扰?当面对TB级数据和复杂查询时,传统数据库往往需要数分钟甚至数小时才能返回结果。本文将通过TPC-H基准测试,展示pg_duckdb如何突破这一限制,为OLAP(在线分析处理)场景带来革命性的性能提升。读完本文,你将了解pg_duckdb在不同数据规模和索引配置下的表现,掌握如何通过Docker快速部署测试环境,并理解其背后的性能优化原理。
测试环境与配置
为了确保测试的可重复性和准确性,我们采用Docker容器化部署方式,使用官方提供的pg_duckdb镜像。以下是基础部署命令:
docker run --rm -e POSTGRES_HOST_AUTH_METHOD=trust --network=host -d --name pgduck -e MOTHERDUCK_TOKEN \
pgduckdb/pgduckdb:17-main
对于生产环境的基准测试,建议根据硬件配置调整PostgreSQL参数。例如,在AWS c6a.8xlarge实例(32 vCPU,64GB RAM)上,推荐配置:
docker run --rm -e POSTGRES_HOST_AUTH_METHOD=trust --network=host -d --name pgduck -e MOTHERDUCK_TOKEN \
--shm-size=64g \
pgduckdb/pgduckdb:17-main \
-c shared_buffers=32GB \
-c max_parallel_workers=32 \
-c max_parallel_workers_per_gather=8 \
-c duckdb.max_workers_per_postgres_scan=8 \
-c duckdb.threads_for_postgres_scan=8
测试工具方面,我们使用项目内置的TPC-H测试脚本scripts/tpch/run.py。该脚本支持多种测试场景,包括不同数据规模、索引配置和执行引擎的对比。
TPC-H测试设计
TPC-H是由事务处理性能委员会(TPC)制定的面向决策支持系统的基准测试,包含8张表、22个复杂查询,涵盖了大量的聚合、连接和子查询操作。我们的测试主要关注以下几个方面:
数据规模
测试使用不同的TPC-H比例因子(Scale Factor),从0.01(约10MB)到10(约10GB),以模拟不同数据量级下的性能表现。比例因子的设置通过--scale-factor参数实现:
./run.py --scale-factor 0.01 --duckdb-engine --pg-engine # 小规模测试
./run.py --scale-factor 10 --duckdb-engine --pg-engine # 大规模测试
索引配置
为了评估索引对性能的影响,测试提供了三种索引策略:
- 全索引:创建所有推荐的索引,包括主键、外键和辅助索引(使用schemas/create-schema.sql)
- 仅主键:只创建主键索引(使用schemas/create-schema-pk.sql)
- 无索引:不创建任何索引(使用schemas/create-schema-no-indexes.sql)
通过--no-indexes和--pk-only参数可以选择不同的索引配置:
./run.py --scale-factor 10 --duckdb-engine --pg-engine --no-indexes # 无索引
./run.py --scale-factor 10 --duckdb-engine --pg-engine --pk-only # 仅主键
执行引擎对比
测试对比了三种执行引擎:
- PostgreSQL:原生PostgreSQL执行引擎
- DuckDB:pg_duckdb内置的DuckDB执行引擎
- MotherDuck:DuckDB的云原生版本(需要额外配置令牌)
通过--pg-engine、--duckdb-engine和--motherduck参数可以启用不同的引擎:
./run.py --scale-factor 10 --duckdb-engine --pg-engine --motherduck # 三引擎对比
测试结果与分析
全索引配置下的性能对比
在比例因子为10(约10GB数据)、全索引配置下,AWS c6a.8xlarge实例上的测试结果如下:
从左图的绝对性能来看,DuckDB引擎在几乎所有查询中都显著优于PostgreSQL。特别是Q1、Q6和Q18等包含大量聚合和连接操作的查询,DuckDB的响应时间仅为PostgreSQL的1/10到1/20。右图的相对性能对比更直观地展示了这一点,DuckDB在大多数查询中实现了5倍以上的加速,部分查询甚至达到20倍。
仅主键配置下的性能对比
当仅创建主键索引时,测试结果如下:
由于缺少辅助索引,PostgreSQL的性能进一步下降,而DuckDB的优势更加明显。在这种配置下,DuckDB的平均加速比提升到8倍左右,部分查询(如Q1和Q12)的性能差距甚至达到了两个数量级。这得益于DuckDB先进的列存储和向量化执行引擎,使其在缺少索引的情况下仍能高效处理复杂查询。
冷启动与热启动对比
测试还区分了冷启动(数据首次加载后立即执行查询)和热启动(数据已缓存,重复执行查询)两种场景。结果显示,PostgreSQL在热启动时性能有显著提升(平均约2倍),而DuckDB的冷热启动性能差异较小。这表明DuckDB的内存管理和缓存机制更加高效,能够更好地利用系统内存资源。
关键性能优化点
pg_duckdb之所以能在TPC-H测试中取得优异成绩,主要得益于以下几个关键技术:
列存储与向量化执行
DuckDB采用列存储格式,相比PostgreSQL的行存储,在分析查询中可以显著减少IO操作。同时,其向量化执行引擎能够一次性处理一批数据,大幅提高CPU利用率。相关实现可参考src/execution/vectorized/目录下的代码。
查询优化器
DuckDB的查询优化器能够生成更高效的执行计划,特别是在处理多表连接和复杂子查询时。例如,在TPC-H Q17(涉及子查询和聚合)中,DuckDB能够选择最优的连接顺序和聚合策略,而PostgreSQL往往陷入嵌套循环的低效执行路径。优化器的核心实现位于src/planner/目录。
内存管理
pg_duckdb引入了专门的内存管理机制,通过src/utility/memory.cpp实现高效的内存分配和回收,减少了传统数据库中常见的内存碎片化问题。这使得在处理大规模数据集时,pg_duckdb能够保持稳定的性能。
如何复现测试结果
如果你想亲自验证这些测试结果,可以按照以下步骤操作:
- 克隆项目仓库:
git clone https://gitcode.com/GitHub_Trending/pg/pg_duckdb.git
cd pg_duckdb/scripts/tpch
- 安装依赖:
pip install -r requirements.txt
- 运行基础测试:
./run.py --scale-factor 0.01 --duckdb-engine --pg-engine
- 生成对比图表:
脚本会自动将测试结果保存到results/目录,并生成类似本文所示的对比图表。你可以通过调整--scale-factor、--no-indexes等参数来模拟不同场景。
结论与展望
通过TPC-H基准测试,我们证明了pg_duckdb在OLAP场景下的卓越性能。无论是全索引、仅主键还是无索引配置,DuckDB引擎都能显著超越传统PostgreSQL的性能,平均加速比可达5-10倍,部分查询甚至达到20倍以上。这一突破为PostgreSQL用户提供了一种无需迁移数据即可获得高性能分析能力的解决方案。
未来,随着DuckDB引擎的不断优化和更多特性的集成,pg_duckdb有望在更广泛的场景下替代传统的OLAP解决方案。我们建议在实际应用中,根据数据规模和查询复杂度,合理选择执行引擎和索引策略,以充分发挥pg_duckdb的性能潜力。
如果你对测试结果有任何疑问,或想了解更多优化技巧,请参考项目官方文档docs/或参与社区讨论。让我们共同推动PostgreSQL生态系统在分析领域的进一步发展!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考





