PostgreSQL 17: EXPLAIN 新选项 MEMORY

John Doe 八月 28, 2025

PostgreSQL 的 EXPLAIN 新增的 MEMORY 选项,可额外输出查询规划阶段的内存消耗信息。

与 SQL 共舞的大象

特性提交日志

添加 EXPLAIN (MEMORY) 以报告规划器内存消耗。

当指定 MEMORY 选项时,会在 “Planning:” 分组下新增一行 “Memory:”,该分组目前仅包含一行 “Buffers:”。

为使报告具备合理的准确性,我们为规划器操作创建了一个独立的内存上下文,且仅在指定该选项时才使用此上下文。该上下文分配的内存总量会以 “allocated”(已分配)形式报告;我们从该总量中减去上下文空闲列表中的内存,并将结果以 “used”(已使用)形式报告。上述数值均通过调用MemoryContextStatsInternal()函数获取。

讨论:https://www.postgresql.org/message-id/CAExHW5sZA=5LJ_ZPpRO-w09ck8z9p7eaYAqq3Ks9GDfhrxeWBw@mail.gmail.com

示例

长期以来,PostgreSQL 在涉及分区表连接的查询规划过程中,会消耗大量的内存,随着连接的表分区数量的增加,内存消耗可能呈指数级增长。相关讨论可参考 [1][2][3]

PostgreSQL 会将关系(表、索引等)的元数据存储在系统表中,如pg_classpg_attributepg_index等。如果每次执行查询时,都直接从磁盘上的系统表中查询这些信息,速度会非常缓慢。因此,每个后端进程都会在内存中维护一个关系缓存 “relation cache”,以提升元数据的访问效率。

当查询涉及大量的表分区时,需要构建的关系缓存的数量也随之增长,最后产生大量的内存消耗。

PostgreSQL 17 为 EXPLAIN 新增了 MEMORY 参数选项,用于显示查询规划器所使用及分配的内存大小,单位为千字节(kB)。该参数的默认状态为关闭(off)

需要注意的是,auto_explain 扩展的功能并不支持 MEMORY 参数。

以下是一个简单示例:

explain (analyze, buffers, memory) select * from people;
                                                 QUERY PLAN
-----------------------------------------------------------------------------------------------------------
 Seq Scan on people  (cost=0.00..1638.07 rows=100007 width=23) (actual time=0.291..11.928 rows=100007 loops=1)
   Buffers: shared read=638
 Planning:
   Buffers: shared hit=17 read=6
   Memory: used=6kB  allocated=8kB
 Planning Time: 1.351 ms
 Execution Time: 18.828 ms

非常不错的新特性,这样就可以轻松识别出那些重度消耗内存的查询了。感谢社区的所有相关人员。

参考

提交日志:https://git.postgresql.org/pg/commitdiff/5de890e3610d5a12cdaea36413d967cf5c544e20