用COPY命令往PostgreSQL里灌数据,速度快是快,但遇到大文件时有个让人头疼的问题:命令一旦敲下去,终端就只剩一个闪烁的光标,你不知道它到底跑了多少、还要跑多久,是正常工作中还是卡死了,只能干瞪眼。从PostgreSQL 14开始,官方提供了一个专门的进度视图pg_stat_progress_copy,让COPY的执行过程变得透明可见。这篇文章就来把这个视图的字段、查询方法以及实际使用中的细节讲清楚。

pg_stat_progress_copy视图包含哪些字段
pg_stat_progress_copy是一个系统视图,底层依托的是PostgreSQL通用的进度汇报框架(progress reporting infrastructure)。执行COPY命令的后端进程会在处理过程中定期把自己的状态写回到共享内存,外部会话通过查询这个视图就能读到这些快照信息。要查看它的完整结构,可以直接执行\d+ pg_stat_progress_copy或者查询系统目录。
视图的字段大致可以分为两类。第一类是通用字段:pid表示执行COPY的后端进程号,可以用它和pg_stat_activity关联,查到对应的会话和执行的SQL语句;datid和datname标识所在的数据库。第二类是COPY专属字段,几个核心的包括:command显示当前执行的是COPY FROM还是COPY TO;type区分数据来源是客户端、程序还是服务端文件;bytes_processed和bytes_total分别记录已处理的字节数和预估的总字节数;tuples_processed记录已处理的行数;tuples_excluded记录被WHERE条件排除的行数(这是PostgreSQL 16新增的能力,配合COPY ... WHERE子句使用)。
值得一提的是bytes_total这个字段。当数据来源是服务端文件时,文件大小是确定的,这个值就是准确值;而当数据来自客户端(比如psql的\copy或者驱动的流式写入)时,总量事先未知,此字段为NULL。这种情况下可以只关注bytes_processed的增长趋势来估算速度。另外current_file和current_file_offset这对字段在COPY涉及多个文件(比如目录形式的COPY FROM DIRECTORY)时非常有用,能精确定位当前正在处理哪个文件以及文件内的偏移位置。
如何查询和监控COPY进度
最基础的用法很简单。在一个会话中启动COPY命令,在另一个会话里查询视图即可。先在会话A中执行一个大文件的导入:
-- 会话A:导入一个大CSV文件 COPY orders FROM '/data/orders_big.csv' WITH (FORMAT csv, HEADER true);
然后在会话B中查询进度:
SELECT
pid,
command,
type,
bytes_processed,
bytes_total,
round(100.0 * bytes_processed / NULLIF(bytes_total, 0), 2) AS pct,
tuples_processed,
tuples_excluded
FROM pg_stat_progress_copy;查询结果会类似这样:pid是12345,command是COPY FROM,pct是37.5,表示已经处理了大约三分之一。如果连续执行几次这个查询,两次的bytes_processed差值除以时间间隔,就能算出实际的导入吞吐量,进而估算剩余时间。可以把它包装成一个带自动刷新的监控脚本:
-- 每隔2秒采样一次,观察吞吐量变化
SELECT
clock_timestamp() AS sample_time,
bytes_processed,
tuples_processed,
bytes_processed - lag(bytes_processed) OVER (ORDER BY clock_timestamp()) AS delta_bytes
FROM pg_stat_progress_copy;如果想让结果更直观,还可以结合pg_stat_activity拿到正在执行的SQL文本,配合pg_size_pretty把字节数转成人类可读的格式,输出一份完整的监控报告。需要提醒的是,进度视图本身查询代价极低,只是读共享内存快照,所以高频率轮询也不会对COPY性能造成明显影响。
使用中的注意事项和常见误区
第一个要注意的点是版本兼容性。pg_stat_progress_copy是PostgreSQL 14才加入的,在那之前的版本里查询这个视图会直接报表不存在。如果你的环境还是12或13,要么升级,要么只能通过对比表的数据量增长(比如定期count,代价很高)或者观察进程IO来侧面判断。目前PostgreSQL各个进度视图都遵循相似的命名规范,比如pg_stat_progress_vacuum、pg_stat_progress_analyze、pg_stat_progress_basebackup等,学会一个之后其他的查看方式基本可以触类旁通。
第二个点是COPY FREEZE的影响。从PostgreSQL 16开始,COPY在满足条件时会尝试直接在页面级别提前执行冻结操作以加速后续的VACUUM,这个优化路径下的进度汇报依然正常工作,但在一些极端情况下(例如启用了wal_level=minimal并执行表截断式优化),部分字段的语义可能和直觉有出入,解读数据时要结合具体的执行计划来分析。
第三个常见误区是把tuples_excluded当成错误行。这个字段统计的是被WHERE子句过滤掉的行,属于正常的业务行为,不是导入失败。真正解析失败导致的行,会直接报错中断COPY(除非使用了ON_ERROR IGNORE这类容错选项,那是17的新特性,跳过的错误行会有单独的统计途径)。监控时如果发现bytes_processed长时间不动、CPU和IO也很低,多半是出现了锁等待或者网络阻塞,此时可以关联pg_locks和pg_stat_activity.wait_event进一步定位原因。
总结
pg_stat_progress_copy把原本黑盒的COPY过程变成了可观测的操作,字段设计覆盖了命令类型、数据来源、字节数、行数、文件位置等关键维度。对于日常大批量数据导入的场景,建议把它纳入运维监控工具箱,配合采样脚本计算吞吐量和剩余时间,可以显著减少等待过程中的不确定性。同时在排查COPY卡顿问题时,这个视图配合pg_stat_activity也是第一入口,先看进度是否还在推进,再判断是性能问题还是锁等待,排查路径会清晰很多。
pg_stat_progress_copyPostgreSQL COPY进度监控修改时间:2026-09-11 09:50:39