Lakebase Postgres 借助 LTAP 将 TB 级数据加载提速至分钟级
DataHot 速览
传统 Postgres 在批量加载 TB 级数据或全表分析时,会与在线事务业务争抢资源,可能造成性能下降甚至停机。Lakebase Postgres 通过 LTAP 架构把重批量操作从主计算卸载到 Spark,让事务和分析引擎处理湖中的同一份数据。beta 客户每天用 Synced Tables 加载约 10 亿行;此前一次批量加载超过 8 小时,并打满 CPU 和内存,即使自动扩缩容也需大幅过度配置 OLTP 资源。卸载到 Spark 后,加载大幅加速,在线应用负载未受影响,应用可更及时获得新数据。
为什么值得关注:数据平台与湖仓从业者应关注其 LTAP 架构如何隔离批量导入与在线事务,并用 Spark 卸载每日十亿行级加载,保护 Postgres 生产性能。
本文目录 8 节
译文
AI 逐段翻译像 Postgres 这样的操作型数据库,其构建目标是可靠地在数据子集上执行高并发、低延迟的查询。而常常影响这种可靠性的,是批量操作,例如加载数 TB 的数据,或运行扫描整张表的分析查询。这些操作会与你的应用程序工作负载争抢相同的资源,从而导致性能下降或停机。
我们的目标是让 Lakebase Postgres 成为你的操作型工作负载最安全、最可靠的地方。我们通过将繁重的批处理操作从主计算卸载到专为这类任务而构建的分布式引擎(如 Spark)来实现这一点。这得益于 LTAP(Lake Transactional/Analytical Processing,湖仓事务/分析处理)架构,它允许事务型和分析型引擎在湖仓中处理完全相同的同一份数据。
如果没有这种隔离,团队常常被迫对批量操作格外小心。他们牺牲数据新鲜度,在非高峰时段不频繁地运行加载,并手动管理复杂的回填和检查点。如今,借助 LTAP 架构,他们可以将摄取管道完全卸载到 Spark,确保应用获得新鲜数据,同时不损害在线系统的性能。
用数据说话
在我们的测试阶段,有一位客户使用 Synced Tables 每天向 Lakebase 加载约 10 亿行数据。借助 LTAP 架构,我们大幅加速了这些加载,同时使其操作型工作负载完全不受影响。

此前,他们的批量加载耗时超过 8 小时,并完全占满了 CPU 和内存。即使有 Lakebase 的自动扩缩容,他们也被迫大量超额配置 OLTP 资源,仅仅为了撑过这次同步。出现这种情况是因为传统 Postgres 架构让主节点成为持久状态的唯一守门人。批量加载被迫通过这一单一瓶颈,意味着每一行导入数据都会在服务于你实时应用流量的同一实例上生成堆页、更新索引并写入 WAL 记录。
LTAP 架构彻底缓解了其主实例的压力,保护了其实时应用流量。你可以获得分布式引擎的全部能力,加载吞吐量随着数据增长几乎线性扩展。我们的内部基准测试显示,现在加载 1 TB 只需不到 5 分钟。

注意:该基准测试衡量的是数据加载时间(构建堆页)。我们也在积极为这些已加载数据实现索引构建的并行化。

在本文的剩余部分,我们将深入探讨向 Postgres 这样的 OLTP 数据库批量加载数据所面临的挑战,并探索我们如何利用 LTAP 架构来解决这些问题。
向 Postgres 大规模批量加载数据的问题
原生 Postgres 的 COPY 命令对于标准、较小规模的摄取是高效的。
但随着客户将其操作型和分析型数据资产拉得更近,规模发生了变化。一种日益常见的工作负载涉及以操作型查询模式向应用提供海量、金牌级 Lakehouse 表。将如此极端体量的数据推入生产数据库会暴露两个根本性限制:
- 加载本质上很慢,因为每一行导入数据都必须经由单一主写入器。
- 用于加载的同一份计算资源同时也在服务于你的应用查询。批量加载需要大量 CPU、I/O、连接和 WAL 带宽,与你的 OLTP 流量争抢资源。
即使你将加载作为分布式 Spark 作业启动,这一点依然成立。Spark 可以并行读取源分区,但每一行仍然必须经过一个 Postgres 写入器:
- 工作节点通过
COPY - 将行发送到 Postgres
- 主节点将这些行转换为堆页和索引页
- 主节点将变更记录到预写日志(WAL)中
展开
传统批量加载受限于单一写入器
源端可以水平扩展,但目标端不行。增加 Spark executor 可以加快扫描,但并不能消除单一写入器瓶颈。此外,同一个 Postgres 主节点还在服务于你的在线应用事务。大规模导入会与它们争抢 CPU、内存、I/O、连接和 WAL 带宽。延迟上升,团队将加载安排在安静的时间窗口,而且他们常常按照最大导入而非日常流量来配置主节点。
LTAP 改变了什么
这一 LTAP 架构 开辟了一条绕过此限制的路径,因为主节点不再是创建持久 Postgres 状态的唯一途径。在 Lakebase 中,事务型计算是无状态的:持久状态存在于分布式存储层,而不是主节点的本地磁盘上。在某种意义上,Postgres 是存储的客户端——它提供查询和事务服务,但它不必是物化每一个新页的进程。

对于批量加载而言,这意味着 Spark 可以构建 Postgres 状态并将其写入存储,而主节点只需发布结果。
其运营层面的结果是:
- 批量加载不会在主节点上与 OLTP 争抢资源。它在实时计算端点之外运行。应用工作负载保留其所需的 CPU、I/O、连接和 WAL 带宽。
- 向同一目标的大型加载可以并发运行。每次导入最终只在主节点上写入一条 WAL 记录,因此加载不再排队等待彼此的
COPY流。 - 主节点无需随加载规模扩缩容。一个 1 CU 的主节点可以持续服务流量,同时 Spark 在单独的计算资源上加载数十亿行,并且 Spark 计算在加载完成后立即终止。
展开
安全且并行地构建有效的 Postgres 页
构建 Postgres 文件和构建主键索引有不同的优化方式。
并行构建堆
Spark 生成的页必须对目标数据库有效,就如同其主节点构建的一样。
每个 Spark executor 都会以 binary-upgrade 模式启动一个沙箱化的 Postgres 实例,这与 pg_upgrade 用来在大版本升级中保留目录 OID。我们用它把目标端的目录 OID 移植到每个沙盒中,确保生成的页面里嵌入的 OID 与目标端一致。该驱动器还会为沙盒分配互不重叠的 OID 范围,使并发创建的对象不会发生冲突。
在每个沙盒内,一个二进制 COPY 配合 FREEZE 构建该执行器的堆切片。冻结会把导入的元组标记为已提交,这样 Postgres 无需查询沙盒中的事务历史即可将其视为可见。
随后每个工作器为每个生成的页面计算校验和。Lakebase 的页面服务器在摄取文件时会验证这些校验和,在导入页面成为权威数据之前检测损坏。
二进制升级模式、冻结元组、协调 OID 和校验和验证共同确保 Spark 生成的页面能被目标端当作普通 Postgres 页面读取。我们通过 Postgres 扩展和表访问方法实现这一点,而无需修改 Postgres 核心代码。
一次性沙盒还允许进行性能优化,例如 UNLOGGED 辅助表。这些是优化手段,而非安全机制:它们避免不必要的 WAL 和锁争用,因为没有应用流量共享该沙盒。
| 这还算是“纯粹的 Postgres”吗? |
|---|
| 是的。Spark 写入的文件就是 Postgres 页面,而不是之后由主库转换的导入格式。我们围绕这条路径添加了扩展和表访问方法,这正是 Postgres 的超能力之一,使我们能够在不修改源代码的情况下扩展其能力。 |
不扫描堆来构建索引
B-tree 是整个键空间上的一个有序结构,其叶条目包含指回堆的键和元组 ID 对。
通常,Postgres 通过扫描堆来获得这些对。然而在这里,堆分布在已上传的切片中,将其全部下载到构建索引的工作器上会抵消并行构建的大部分收益。
索引构建器实际上并不需要堆的内容。它需要的只是堆扫描会产生的 (key, ctid) 对组成的流。因此,上一步中的每个堆工作器在构建其切片时,会把它的键列和元组 ID 导出到一个单独的对象存储文件中。
我们将这些记录送入一个辅助表,其中只包含导出的键列和元组 ID,而不是原始行。在 CREATE INDEX 期间,一个自定义表访问方法像 heapam 一样扫描该辅助表,但会将 ctid 写入每个索引条目,而不是辅助行自身的物理元组 ID。在加载记录时,每个切片本地的 ctid 会按先前堆切片的累计大小进行偏移,使其指向该元组在拼接后堆中的最终位置。简而言之,Postgres 的标准 B-tree 构建器可以原封不动地扫描这个辅助表,并在一个它从未下载过的堆上生成索引。这将整个堆的移动替换为小得多的键和元组 ID 表示的移动。
把结果交给 Postgres
一旦堆和索引切片进入对象存储,Spark 驱动器就会写入一个清单,并在目标端调用一个 SQL 函数。主库将该导入记录为一条紧凑的 WAL 记录。常规的 COPY 会把完整的数据量通过 safekeeper 法定人数发送。而我们只发送导入描述。
页面服务器会将上传的文件认领为权威页面并验证其校验和。它们还会将页面预热到本地 SSD,使初始读取不会产生冷对象存储获取。最后,主库将暂存数据原子地交换为对用户可见的已同步表。
在该事务提交之前,导入的表保持隔离。之后,主库看到的是通过标准 Postgres 格式和接口生成的普通堆和 B-tree 页面。
立即开始使用。
我们使用 LTAP 架构来驱动 Synced Tables,从而在从你的 Lakehouse 提供黄金数据集时实现更快的同步。如果你正在从 Lakehouse 运行手动 ReverseETL 作业,有了 Lakebase,你应该考虑使用 Lakebase。
我们很高兴将这一协议推广到处理大型操作和维护,比如构建索引甚至迁移。采用 LTAP 架构的 Lakebase 是运行 OLTP 工作负载的最佳场所。
如果你还没有尝试过 Lakebase 和 Synced Tables,立即开始使用。
这篇内容对你有用吗?
反馈只用于改善内容筛选,不等同于收藏