work_mem 调优

本页目录

work_mem 用于查询执行期间排序和哈希操作的内存分配。默认情况下,其大小为 4MB。 由于其性质,调优 work_mem 相对复杂。

这里介绍了一种可能的调优方法。

work_mem 的粗略调优和安全值

首先,按照 Day 89: Rough configuration tuning (80/20 rule; OLTP) 中的描述进行粗略优化。

一个查询可能会多次"消耗" work_mem (用于多个操作)。但是,并不是为每个操作都完全分配 — 一些操作可能只需要较少的内存。

因此,很难可靠地预测处理工作负载时需要使用多少内存,而不经过对工作负载的实际观察。

PostgreSQL 13 引入了 hash_mem_multiplier,用于设置哈希操作相对于 work_mem 的内存倍数。单个哈希操作的内存上限为 work_mem * hash_mem_multiplier。

译者校订:原文将 PostgreSQL 13–16 的默认值统称为 2,并不准确。PostgreSQL 13 文档中的默认值为 1.0;实际配置请通过 SHOW hash_mem_multiplier 确认。只有该值为 2 时,上限才是 2 * work_mem。

值得一提的是,在 Linux 中了解会话使用了多少内存本身是非常困难的 — 可以参考Andres Freund 的精彩文章:Analyzing the Limits of Connection Scalability in Postgres (2020 年)。

一种安全的调优方法是:

在实践中,调整 work_mem 至一个较高值是有意义的,但前提是理解了 PostgreSQL 在特定工作负载下的行为之后再进行。以下步骤是进一步调优的迭代方法的一部分。

临时文件监控

监控临时文件的创建频率及其大小。相关信息来源:

进一步调优 work_mem 的目标是完全消除临时文件的创建,或尽量减少其创建频率和大小。

优化查询

如果可能,考虑优化那些涉及临时文件创建的查询。为此投入适当的精力 — 如果没有明显的优化空间,继续执行下一步。

进一步提升work_mem:多少合适?

如果已经做了合理的优化工作,现在可以考虑进一步提高 work_mem。

然而,提升多少合适呢?答案取决于单个临时文件的大小 — 通过上面描述的监控,我们可以找到最大和平均临时文件大小,并从中估算所需的提升量。

🎯 TODO: 详细步骤

针对部分工作负载提升work_mem

针对单个查询提高 work_mem 是有意义的。考虑两种方式:

全局提升work_mem

只有在前述步骤不适用时 (例如,查询优化困难且无法针对部分工作负载调优 work_mem) 才考虑全局提升 work_mem,同时评估 OOM 的风险。

迭代优化

一段时间后,审查监控数据,确保情况有所改善,或决定进行下一次迭代。

额外内容:pg_get_backend_memory_contexts

在 PostgreSQL 14 中,新增了一个函数 pg_get_backend_memory_contexts() 及其对应的视图;请参考文档。这对于详细分析当前会话如何使用内存非常有帮助,但该功能的主要限制是它只能与当前会话一起使用。

🎯 TODO: 如何使用它。

讨论与补充

在 GitHub 查看讨论

支持作者

感谢支持 PostgreSQL Howto 的长期维护。

微信赞赏码

读者交流群

二维码若已过期,可通过公众号 PostgreSQL 学徒或邮件联系。

PostgreSQL 学徒读者交流群二维码