我在2025年开发的新 PostgreSQL 功能
Source: Dev.to
概览
我大约在2020年开始为 PostgreSQL 做贡献。到了2025年,我想更加努力,于是我将在本文中说明今年我开发并提交的 PostgreSQL 功能。
我也提交了一些其他补丁,但它们都是错误修复或小的文档更改。下面列出的是看起来最有用的那些。
注意: 这些主要是 PostgreSQL 19 中的功能,当前仍在开发中。它们可能在最终发布前被撤回。
1. 推荐在恢复 pg_dump 备份时的默认 psql 设置
- 标题: 文档:建议在恢复 pg_dump 脚本时使用 “psql ‑X”
- 提交者: Tom Lane
- 日期: 2025 年 1 月 25 日,星期六
当你使用 psql 恢复由 pg_dump 生成的转储文件时,如果 psql 使用了非默认设置(例如 AUTOCOMMIT=off),可能会出现错误。此更改仅涉及文档:建议使用 psql 选项 -X(--no-psqlrc)来避免读取 psqlrc 配置文件。
关于我过去关于 psqlrc 文件的博客,请参见:
示例
# create a test database
createdb test1
# dump all databases to an SQL script file
# -c issues DROP for databases, roles, and tablespaces before recreating them
pg_dumpall -c -f test1.sql
# restore with psql (without -X)
psql -f test1.sql
# → errors:
# psql:test1.sql:14: ERROR: DROP DATABASE cannot run inside a transaction block
# psql:test1.sql:23: ERROR: current transaction is aborted, commands ignored until end of transaction block
# …
DROP DATABASE(由 -c 生成)不能在事务块内部执行,因此会出现上述错误。默认情况下,当事务块中的语句失败时,整个事务会中止,导致后续语句也失败。使用 psql -X 可以避免此问题。
Source: …
2. 为 pg_stat_progress_basebackup 视图添加 backup_type 列
- 标题: 为 pg_stat_progress_basebackup 添加 backup_type 列
- 提交者: Masahiko Sawada
- 日期: 2025 年 8 月 5 日 星期二
PostgreSQL 17 为 pg_basebackup 添加了增量备份支持,但 pg_stat_progress_basebackup 视图没有列来指示备份是完整的还是增量的。新增的 backup_type 列会显示 full 或 incremental。
演示
# 完整备份
pg_basebackup -D full
SELECT * FROM pg_stat_progress_basebackup;
-[ RECORD 1 ]--------+-------------------------
pid | 853626
phase | streaming database files
backup_total | 1592460800
backup_streamed | 622124544
tablespaces_total | 1
tablespaces_streamed | 0
backup_type | full -- new!
# 增量备份
pg_basebackup -i full/backup_manifest -D incl
SELECT * FROM pg_stat_progress_basebackup;
-[ RECORD 1 ]--------+-------------------------
pid | 854435
phase | streaming database files
backup_total | 1613615104
backup_streamed | 726617088
tablespaces_total | 1
tablespaces_streamed | 0
backup_type | incremental -- new!
3. COPY FROM 现在支持具有多行标题的文件
- 标题: 在 COPY FROM 命令中支持多行标题
- 提交者: Fujii Masao
- 日期: Thu, 3 Jul 2025
COPY 命令的 HEADER 选项用于控制标题的处理方式。以前,COPY FROM 只能跳过单行标题(布尔值)。现在它接受整数,可以跳过任意数量的标题行。
示例
\! cat /tmp/copy.csv
first header
second header
1,one
2,two
3,three
COPY t FROM '/tmp/copy.csv' WITH (HEADER 2, FORMAT csv);
-- COPY 3
TABLE t;
id | data
----+------
1 | one
2 | two
3 | three
(3 rows)
其他 RDBMS 中的类似功能
| RDBMS | 语法 |
|---|---|
| MySQL | LOAD DATA ... IGNORE N LINES |
| SQL Server | BULK INSERT … WITH (FIRSTROW = N) |
| Oracle SQL*Loader | sqlldr … SKIP=N |
4. 将 autovacuum 日志设置拆分为 VACUUM 和 ANALYZE
- 标题: 添加
log_autoanalyze_min_duration - 提交者: Peter Eisentraut
- 日期: Wed, 15 Oct 2025
我们之前已经有 log_autovacuum_min_duration,它会记录由 autovacuum 执行的 VACUUM 和 ANALYZE,当它们超过配置的时长(默认单位:ms)时。此更改引入了一个独立的设置 log_autoanalyze_min_duration,这样你就可以独立控制 ANALYZE 的日志记录,而不影响 VACUUM。
(其余描述继续出现在原始提交信息中。)
ANALYZE 与 VACUUM 日志
ANALYZE 主要读取抽样行,而 VACUUM 则 读取并写入 表和索引页,所以 VACUUM 通常耗时更长(这取决于表结构、数据量、统计目标、工作负载、扩展统计等因素)。我们无法将日志时长参数分别设置。
现在 log_autovacuum_min_duration 仅针对 VACUUM,而新加入的 log_autoanalyze_min_duration 仅针对 ANALYZE。最初我们提出使用 log_autovacuum_vacuum_min_duration 和 log_autovacuum_analyze_min_duration 以保持一致性,但更改已有名称会破坏向后兼容性,并影响 pg_dump/pg_upgrade,于是放弃了该方案。
=# CREATE TABLE t (i int, d text) WITH (
-- autoanalyze settings
autovacuum_analyze_threshold = 1,
autovacuum_analyze_scale_factor = 0,
log_autoanalyze_min_duration = 0,
-- autovacuum settings
autovacuum_vacuum_threshold = 1,
autovacuum_vacuum_scale_factor = 0,
log_autovacuum_min_duration = 100_000_000
);
=# INSERT INTO t VALUES (1, 'a');
=# DELETE FROM t WHERE i = 1;
2025-12-03 15:15:39.608 JST [401368] LOG: automatic analyze of table "postgres.public.t"
avg read rate: 18.229 MB/s, avg write rate: 0.000 MB/s
buffer usage: 155 hits, 7 reads, 0 dirtied
WAL usage: 1 records, 0 full page images, 530 bytes, 0 buffers full
system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s
在 pg_stat_wal 中显示压缩的全页图像大小
- 标题: 将
wal_fpi_bytes添加到pg_stat_wal和pg_stat_get_backend_wal() - 提交者: Michael Paquier
- 日期: 2025年10月28日 星期二
当 wal_compression 开启时,WAL 中的全页图像(FPI)会被压缩。
以前,衡量其效果需要:
- 在开启/关闭压缩的情况下运行相同的基准测试,并比较
pg_stat_wal中的wal_bytes。这会测量 所有 WAL,而不仅仅是 FPI,因此压缩比是近似的。 - 在服务器上运行
pg_waldump --fullpage来查看压缩后的 WAL 大小并计算比率。这需要 WAL 文件和服务器访问,在许多云环境中不可行。
该补丁向 pg_stat_wal 添加了 wal_fpi_bytes:
=# SELECT * FROM pg_stat_wal;
-[ RECORD 1 ]----+-----------------------------
wal_records | 2031667
wal_fpi | 288581
wal_bytes | 6346674376
wal_fpi_bytes | 1932610356 -- new!
wal_buffers_full | 424447
stats_reset | 2025-12-02 19:31:44.16184+09
还有将此信息暴露在 EXPLAIN (WAL) 和 VACUUM 日志中的补丁。[4][5]
为 pg_stat_progress_vacuum 视图添加 mode 和 started_by 列
- 标题: 为
pg_stat_progress_vacuum视图添加mode和started_by列。 - 提交者: Masahiko Sawada
- 日期: Tue, 9 Dec 2025
VACUUM 可以因多种原因启动(自动、手动、回环),并且可以在不同模式下运行(normal、aggressive、failsafe)。之前的进度视图并未公开这些信息。
新增的列如下:
| 列名 | 示例取值 |
|---|---|
mode | normal、aggressive、failsafe |
started_by | manual、autovacuum、autovacuum_wraparound |
示例输出
=# SELECT * FROM pg_stat_progress_vacuum;
-[ RECORD 1 ]--------+--------------
pid | 362895
datid | 5
datname | postgres
relid | 24602
phase | scanning heap
heap_blks_total | 8850
heap_blks_scanned | 5327
heap_blks_vacuumed | 0
index_vacuum_count | 0
max_dead_tuple_bytes| 67108864
dead_tuple_bytes | 0
num_dead_item_ids | 0
indexes_total | 0
indexes_processed | 0
delay_time | 0
mode | normal -- new!
started_by | autovacuum -- new!
类似的补丁为 pg_stat_progress_analyze 添加了 started_by 列(manual、autovacuum)。 [6]
结论
我介绍了我在 2025 年开发的 PostgreSQL 功能,并提出了几项仍在讨论中的额外补丁。希望明年能分享更多。