Pgtestdb 的模板克隆方法使测试速度很快

Hacker News Top 工具

摘要

pgtestdb 是一个 Go/Postgres 测试包,它利用 Postgres 模板数据库快速克隆测试数据库,实现与基于模式的方法相当的设置时间,同时支持完整的端到端测试。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/07/30 16:51

# pgtestdb的模板克隆测试方法速度快 来源:https://brandur.org/fragments/pgtestdb 昨天,我在 *Cup o' Go* (https://cupogo.dev/episodes/proposals-proposals-proposals-and-faster-postgresql-tests-with-peter-downs) 节目中回想起 Peter Downs 的 `pgtestdb` (https://github.com/peterldowns/pgtestdb) 这个 Go/Postgres 测试包的存在。 `pgtestdb` 建立在 Postgres 的**模板数据库** (https://www.postgresql.org/docs/current/manage-ag-templatedbs.html) 之上,这是 Postgres 的一个内置特性,你可以直接在普通的 psql 终端中尝试: ```sql CREATE DATABASE dbname TEMPLATE template_to_copy; ``` 复制模板非常快,远比从头迁移测试数据库要快,而且**远**快于如今某些项目使用的重量级 Docker 方案。在底层,Postgres 会枚举模板的关系,并以 8KB 页块的形式复制其实体化的堆、索引和目录文件。 我记得多年前读到过这个特性,但说实话,我忘了它的存在。我很好奇它与其他测试方法的性能对比,于是让 Codex 将 pgtestdb 集成到 River 的测试套件中,看看表现如何。 我倾向于认为 River 的测试方法在速度和可靠性方面堪称黄金标准。它使用一组自定义测试助手,基于 schema 隔离测试用例。这种方法比**测试事务** (https://brandur.org/fragments/go-test-tx-using-t-cleanup) 慢,但有一些优势: - 测试失败时,保留测试状态以供检查。 - 支持测试数据库级特性,如 listen/notify。 - 支持测试涉及多个事务交互和回滚的边缘情况。 ## 结果 (https://brandur.org/fragments/pgtestdb#results) 在 Postgres 中,schema 比数据库更轻量,因此基于 schema 的方法在这方面有优势。然而,你不能克隆 schema,所以基于 schema 的方法每次都必须运行迁移,这给了 pgtestdb 一个明显的优势。 这应该会提供一个有趣的对比。以下是我得到的结果: | 方法 | 计数 | 平均值 | p90 | p95 | 最大值 | |------|------|--------|-----|-----|--------| | pgtestdb 克隆 | 466 | 98.4ms | 247.4ms | 299.5ms | 465.1ms | | 创建 + 迁移 schema | 81 | 99.4ms | 152.1ms | 209.0ms | 327.0ms | 我们发现,两种方法的耗时非常相似,大约都在 100ms 左右的设置时间。 我一直以为任何涉及创建新数据库的操作都会相对较慢,所以看到 pgtestdb 的方法实际这么快时,我有点惊讶。 我打算保留 River 现有的基于 schema 的测试方法,因为它已经很快,而且测试 schema 隔离顺便有助于验证 River 的**基于 schema 的配置** (https://riverqueue.com/docs/alternate-schema) 是否按预期工作。但我会在我们的文档中推荐 pgtestdb,特别是对于想进行端到端测试(即客户端插入 job → worker 完全完成)的用户。 ## 通过复用进行优化 (https://brandur.org/fragments/pgtestdb#optimizing-via-reuse) 上面我有点保守。虽然基于 schema 的方法的**设置时间**与 pgtestdb 的完整数据库方法相似,但整体测试套件在前者上运行速度快约 3.5 倍: | 方法 | 墙钟时间 | |------|----------| | pgtestdb 克隆 | 51.07s | | 创建 + 迁移 schema | 14.54s | 但这不是因为 schema 快很多。River 的测试助手有一个有用的优化:它们会根据 Go 的即时并行化需求创建尽可能多的测试 schema,并在测试用例完成后将它们池化。如果一个未占用的 schema 已就绪,测试用例会清理并复用它,而不是从头生成一个新的[^1]。 这说起来容易做起来难,因为你需要考虑 schema 版本之类的细节——例如,当跨 schema 版本进行测试时,每个测试用例只能复用与其预期版本相同的 schema。当然,这完全可行,但需要一些思考。我在 LLM 出现之前编写了 River 的实现,花了几天时间才解决所有 bug。 我提到复用的原因是,pgtestdb 也可以做到这一点,可能作为包本身的一部分,或者作为项目中调用它的增强。100ms 来引导一个测试数据库已经很快了,但如果你在构建一个将有 10,000 个测试的完整应用程序,你理想中希望测试设置快 10 倍。复用可以将其降低到 10-20ms,更接近测试事务的水平。 [^1]: 脚注原文未提供,此处保留标记。

相似文章

@ycombinator: Ardent (@ArdentAI) 让你在 TB 级规模下 <6秒 克隆任何 Postgres 数据库,让编码代理可以测试代码,工程团队可以快速上线而不用担心影响生产…

X AI KOLs Following

Ardent 是一款 Y Combinator 支持的工具,能在 TB 级规模下于 6 秒内克隆任何 PostgreSQL 数据库,让编码代理和开发者可以在接近生产环境的克隆副本上测试代码,而不会造成停机风险。该工具已被 Supermemory 和 Surface Labs 等公司采用。

PgDog

Product Hunt

PgDog 是一款无需修改应用程序即可扩展 PostgreSQL 的工具,提供连接池和负载均衡功能。

PgDog 获得融资,即将登陆您的数据库

Hacker News Top

PgDog 是一个开源代理,使 Postgres 实现水平扩展,已从 Basis Set、YC 等机构获得 550 万美元融资。该工具已在生产环境中每秒处理超过 200 万次查询。