PostgreSQL码农集散地

PG 19 让 COPY 导入数据吃上 SIMD 红利性能飙升

本期播客

PG 19 COPY FROM CSV 数据导入吃上 SIMD 红利

你以为 COPY FROM 慢,瓶颈一定在磁盘?
未必。很多时候,磁盘还没喊累,CPU 已经在逐字节啃 CSV 了。

2026 年 3 月 13 日,PostgreSQL 提交了一个很容易被低估、但对 DBA、架构师、应用开发者都很有现实意义的补丁:

e0a3a3fd5361913502ff696ecf47770ca55975ae
标题很直接:Optimize COPY FROM (FORMAT {text,csv}) using SIMD

如果把这句话翻成大白话,就是:

PostgreSQL 不想再老老实实一字节一字节扫文本导入数据了,而是开始让 CPU 一次并行检查一大块字符。

这不是“小修小补”。
这是在改 PostgreSQL 最常见数据入口之一的底层热路径。

而我要先抛出核心观点:

未来数据库导入性能的上限,越来越不只取决于存储吞吐,还取决于你能不能把“文本解析”这件事从标量时代带进 SIMD 时代。

一、很多人对 COPY FROM 的理解,已经过时了

在 DBA 和开发者的语境里,COPY FROM 往往被当成一句经验:

  • 比单条 INSERT 快
  • 比 ORM 批量写快
  • 是 PostgreSQL 最推荐的大批量导入方式之一

这些都没错。
PostgreSQL 官方文档也明确把 COPY 定义为在表与文件/标准输入之间高效搬运数据的机制,并提供了 pg_stat_progress_copy 来跟踪进度。
但问题在于,很多人停在这里,不再往下想。

真正的问题是:

当 COPY FROM FORMAT text/csv 已经不用一条条 SQL 插入后,它下一步的瓶颈会落在哪?

答案通常不是一个,而是两类:

  • I/O:数据读进来够不够快
  • CPU:读进来之后,解析 text/csv 够不够快

而这次 commit 针对的,正是第二类。

PostgreSQL 2026 年度大戏来了, 扫海报中的二维码报名, 选择早鸟或通票(都含午餐和周边礼品), 可私信我要优惠码, 数量有限先到先得!

图片

二、PostgreSQL 之前是怎么干的?一句话:逐字节扫描

根据 PostgreSQL 内核实现和 DeepWiki 对 copyfromparse.c 的总结,COPY FROM text/csv 的关键路径之一,是在输入缓冲区里寻找各种“特殊字符”:

  • 分隔符
  • 引号
  • 转义字符
  • 行结束符
  • 某些特殊结束标记

过去的主路径,本质上是:

一字节一字节扫,看看这个字符是不是“特殊字符”。

这件事听上去平平无奇,甚至很合理。
但在今天的硬件条件下,它会暴露一个非常现实的问题:

CSV 解析不是“高深逻辑”,但它极容易成为 CPU 热点。

为什么?

因为它的操作太频繁了:

  • 每行都要扫
  • 每列都要判
  • 每个字符都可能触发分支
  • 还要维护引号/转义状态

这类逻辑有个典型特征:

单次不贵,次数极多;每步简单,但总量惊人。

一旦你的导入规模上来,比如:

  • 几千万行
  • 上亿行
  • 长字段
  • 多列文本
  • 网络和磁盘都不算慢

CPU 就可能比磁盘更早成为主矛盾。

三、这次优化到底做了什么?本质是“跳过无聊数据”

这次 commit 的核心思想非常漂亮:

既然大多数文本内容并不是特殊字符,那就别每个字节都认真审问。

改法是:

  • 用 SIMD 指令一次检查一大块数据
  • 如果这块里没有特殊字符,就整块跳过
  • 只有发现特殊字符附近时,再退回更细粒度处理

这就是所谓的“SIMD skip over chunks without special characters”。

你可以把它理解成两种工作方式的区别:

旧方式:
保安逐个翻每个人口袋,确认有没有违禁品。

新方式:
先用高效安检门快速扫一批人,没响的一整批直接过,响了再单独查。

这才是现代 CPU 最擅长的事。

四、为什么这是大事?因为文本导入的瓶颈,越来越像“解析问题”而不是“写盘问题”

很多数据库从业者还停留在老时代直觉里:

  • 导入慢,多半是磁盘差
  • 导入快不起来,多半是 WAL 大
  • 调快导入,就是关约束、关索引、改 checkpoint

这些判断有时对,但越来越不完整。

从第一性原理看,COPY FROM text/csv 的总成本,至少包含四段:

  1. 读取原始输入
  2. 文本解析与字段切分
  3. 数据类型转换
  4. 堆写入、WAL、索引、约束、触发器

如果你面对的是现代服务器:

  • NVMe 很快
  • 页缓存很强
  • 内存足够
  • 文件来源本地或高带宽网络
  • 表上索引不多、约束不重

那么主矛盾就可能前移到第 2 步:

文本解析本身。

所以这次优化重要,不是因为它让 COPY “终于变快”,
而是因为它承认了一件很多人不愿承认的现实:

纯文本格式的导入,在很多场景下已经不是 I/O 问题,而是 CPU 解析问题。

五、哪些场景最吃这波红利?哪些场景别高兴太早?

这篇文章最重要的部分,不是喊“SIMD 牛”,而是把边界说清楚。

最可能受益的场景

根据 commit 描述和 PostgreSQL COPY 的解析规则,最容易受益的是这类数据:

  • 行比较长
  • 大段内容没有特殊字符
  • 引号、转义较少
  • CSV 字段内容相对“干净”
  • 分隔符密度不算过高
  • 文本导入量极大,CPU 成本可累计放大

为什么?

因为 SIMD 路径最擅长做的,就是:

快速跳过“绝大多数都很普通”的数据块。

如果一整段字符里没有分隔符、引号、转义符、特殊终止符,那么传统逐字节循环几乎是在浪费 CPU。
SIMD 则能把这段“无聊工作”压缩掉。

受益有限,甚至可能不明显的场景

这次 commit 自己也写得很保守:
为了避免回归,一旦遇到短行或某些特殊字符,SIMD 会对本次 COPY FROM 剩余部分禁用,策略偏保守,未来也许还能更激进。

这句话很关键,意味着以下场景不要盲目乐观:

  • 行很短
  • 引号很多
  • 转义很多
  • CSV 数据很“脏”,特殊字符频繁出现
  • 每行很快就碰到 delimiter/quote/escape
  • 复杂 CSV,经常出现带换行的 quoted field

这种数据模式下,SIMD 很难长时间沿着“整块跳过”快路径奔跑,
很快就要退回普通解析逻辑。

换句话说:

这次优化奖励的是“结构规整、可预测、长段普通字符”的数据。
它不会神奇地把所有脏 CSV 都变快。

六、这不是“所有导入都飞起”,更不是“以后 CSV 可以随便用了”

必须把这层说透。

有些人看到 SIMD,会马上得出两个错误结论:

误判 1:既然 COPY FROM csv 变快了,那文本格式就够了,不用考虑 binary

错。

PostgreSQL 官方文档一直说得很清楚:
binary 格式通常会比 text/csv 更快,只是可移植性和通用性更差。

所以更准确的判断是:

  • 如果你要通用、跨系统、跨语言、方便排查,text/csv 仍然有巨大现实价值
  • 如果你追求极致吞吐,而且上下游都可控,binary 依然可能更强

SIMD 优化提升的是 text/csv 的竞争力,不是抹平它与 binary 的物理差异。

误判 2:内核都优化了,开发者不用关心数据格式质量了

也错。

这次优化恰恰在提醒你:
数据“干净不干净”“规整不规整”,已经不只是 ETL 美学问题,而是 CPU 成本问题。

如果你的 CSV:

  • 引号乱飞
  • 转义过多
  • 每列塞大段复杂文本
  • 行格式高度不稳定

那你就是在主动破坏 SIMD 能发挥作用的前提。

所以从架构角度看,这个 commit 传递的是一个更深的观点:

导入性能,不只是数据库问题,也是数据生产格式的问题。

七、对 DBA、架构师意味着什么?

这次 commit 对 DBA 和架构师的启发,远大于“某个导入任务快一些”。

1. 版本升级的收益,越来越来自热路径瘦身

很多团队评估 PostgreSQL 升级,还停留在这几项:

  • 新 SQL 语法
  • 新索引特性
  • planner 增强
  • 高可用能力

这些当然重要。
但现代 PostgreSQL 真正越来越值钱的一类改动,是这种:

  • AIO
  • SIMD
  • executor 热路径优化
  • tuple deformation 优化
  • maintenance I/O 重构

也就是说:

数据库版本升级的回报,已经越来越多地来自“基础路径更现代化”,而不是“多了一个功能按钮”。

2. COPY FROM 的性能分析,要更细分

以后再看导入慢,不该只问:

  • 磁盘是不是慢
  • WAL 是不是大
  • checkpoint 是不是顶住了

还应该问:

  • CPU 火焰图上,解析占了多少
  • 输入数据是不是大量短行
  • CSV 是否充满引号/转义
  • 实际瓶颈是 parse、cast 还是 heap/WAL

因为这次补丁已经证明:
PostgreSQL 社区自己也承认,COPY FROM 的解析阶段值得单独优化。

这会反过来影响 DBA 的排障思路。

八、对应用开发者意味着什么?

对开发者,这个 commit 其实是一次很直接的提醒:

你提交给数据库的,不只是“数据”,还是“解析负担”。

很多团队在数据导入链路上有个错误习惯:

  • 只关心能不能导进去
  • 不关心格式是否利于解析
  • 只要 CSV 合法就行
  • 上游系统输出怎么方便怎么来

这在规模小时问题不大,
但一旦进入亿级、十亿级导入,问题就很明显:

数据库并不是“读到文件就自动落表”,而是要逐层解析、切字段、转类型、写 WAL。

所以开发者应该从这次 commit 里得到三个实用结论:

  • 如果必须用 CSV,尽量让格式规整,少做无意义 quoting/escaping
  • 如果是系统内部大批量交换,认真评估 binary 或更可控的管道格式
  • 如果你抱怨导入慢,别先骂数据库,先看看上游吐出来的是不是“解析噩梦”

九、第一性原理:什么时候这次优化最值钱?

这篇文章的核心判断,建立在几个前提上。

前提 1:你的 COPY FROM 使用的是 text/csv

因为这次 commit 明确针对的是 FORMAT {text,csv}。
不是 binary,不是其他路径。

前提 2:瓶颈里确实有显著的“逐字符解析成本”

如果你的慢主要来自:

  • 复杂类型转换
  • 唯一索引冲突
  • 触发器
  • 外键检查
  • WAL fsync
  • 网络传输

那 SIMD 再强,也救不了主矛盾。

前提 3:输入数据具有足够长的“普通字符区间”

也就是特殊字符不能太密。
否则 SIMD 快路径根本跑不起来,或很快被禁用。

如果这三个前提同时成立,
这次优化就很有现实意义。

十、如果前提崩了,观点也必须变

这是专业分析和流量文章的分水岭。

如果你的数据是“脏 CSV”

那正确观点不是“PostgreSQL SIMD 不给力”,
而是:

数据模式先天不利于向量化跳过,收益本来就会受限。

如果你的瓶颈在 WAL 或约束

那这次优化的意义就会退居二线。
此时更该优化的是:

  • 减少索引
  • 批量装载策略
  • COPY FREEZE 可行性
  • 关闭非必要触发器
  • 分区装载
  • 调整 checkpoint / wal / autovacuum 协同

如果你本来就用 binary

那这次补丁对你影响不大。
但它依然说明一个趋势:

PostgreSQL 正在连 text/csv 这种“传统、通用、最难极致优化”的入口都拿 SIMD 开刀。

这说明社区在认真追求“默认路径也更快”。

结论

这次 Optimize COPY FROM (FORMAT {text,csv}) using SIMD,不是一个只属于内核开发者的补丁。
它对业务的真正意义是:

PostgreSQL 正在把最常见的数据导入入口,从“逐字节文本处理”推进到“现代 CPU 友好的并行扫描”。

这背后最值得记住的,不是 SIMD 这个词本身,
而是三个现实判断:

  • 导入性能的瓶颈,不一定在磁盘,也可能在文本解析
  • 数据格式质量,不只是兼容性问题,也是吞吐问题
  • 未来 PostgreSQL 的版本价值,会越来越体现在这种底层热路径优化上

所以,对 DBA、架构师、开发者来说,这个 commit 最值得记住的一句话是:

数据库不只是要写得快,还要“看懂文本”更快。


你怎么看

你们线上大批量导入时,主要瓶颈更常出现在哪一层:I/O、WAL、约束,还是文本解析?
如果 PostgreSQL 的 COPY FROM csv 越来越快,你会继续坚持 CSV 通用格式,还是会更认真考虑 binary/自定义导入协议?
评论区聊聊:你觉得“数据格式设计”在导入性能里,应该背多大锅?