由 John Doe 八月 28, 2025
PostgreSQL 的 EXPLAIN 新增的 MEMORY 选项,可额外输出查询规划阶段的内存消耗信息。
特性提交日志
添加 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_class
、pg_attribute
、pg_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