导读:本期聚焦于小伙伴创作的《如何使用pg_prewarm对PostgreSQL缓冲区进行预热提升查询性能》,敬请观看详情。冷启动后的PostgreSQL实例常因表数据未载入共享缓冲区而引发大量磁盘读,使首轮查询明显变慢。pg_prewarm扩展能主动把指定表或索引页面装入内存,减少物理读开销。它支持手动调用函数装载全部或部分关系,也可借助自动预热功能在重启后恢复此前的缓存状态。相比靠业务流量自然加热,主动预热让报表类、定时任务类负载在启动后即可保持稳定延迟。理解其两种工作模式与权限控制,有助于在大型库上安全地缩短预热时间并避免内存争用。

在PostgreSQL中,当数据库实例刚刚启动或者某张大表长时间未被访问时,相关数据页往往还停留在磁盘上,没有进入共享缓冲区。此时业务发起的第一次查询就会触发大量的物理读,响应时间可能比数据已在内存中时慢上数倍甚至数十倍。pg_prewarm是PostgreSQL官方贡献的一个扩展模块,它的作用就是把表、索引或者物化视图的页面主动加载到操作系统的文件系统缓存或数据库的共享缓冲区里,从而让后续的查询直接命中内存,避免冷启动带来的性能陡降。

如何使用pg_prewarm对PostgreSQL缓冲区进行预热提升查询性能

pg_prewarm扩展的两种工作模式

pg_prewarm主要提供两种预热方式。第一种是手动预热,通过调用扩展提供的pg_prewarm函数,由数据库管理员或具备权限的用户显式指定要加载的关系名、加载模式以及页面范围。这种方式非常灵活,可以针对某张大表在批量报表运行前单独加热,也可以编写脚本在每日凌晨业务低峰期依次预热核心表。手动模式的核心在于控制权完全在用户手里,不会在数据库启动时产生额外的自动开销。

第二种是自动预热,依赖shared_preload_libraries中载入pg_prewarm,并配置pg_prewarm.autoprewarm参数为开启状态。数据库会在后台定期把当前缓冲区中的页面记录转储到磁盘文件,当下一次实例重启时,自动预热进程会读取该文件并尝试把记录的页面重新装入共享缓冲区。自动模式适合那些希望实例重启后尽快恢复到重启前缓存状态的场景,比如长期运行的在线服务,但它要求额外的磁盘写入与启动时的加载时间。

两种模式并不冲突,实际生产中常组合使用:自动预热负责基础恢复,手动预热负责针对特定业务高峰的补充加载。需要注意的是,自动预热的记录文件如果过大,重启时读取和加载都会变慢,因此应通过pg_prewarm.autoprewarm_interval合理控制转储频率。

手动预热函数的参数与使用示例

pg_prewarm函数的签名包含关系名、预热模式、缓冲池类型、起始块号和结束块号。预热模式分为prefetchreadbuffer三种。其中prefetch利用操作系统异步预读,不保证页面一定进入数据库共享缓冲区;read会同步读取页面到操作系统缓存;buffer则直接把页面读入PostgreSQL的共享缓冲区,对减少数据库层物理读最有效。缓冲池类型一般使用默认的main即可。

下面是一段手动预热整张订单表的示例,将全部页面装入共享缓冲区:

-- 先创建扩展(需超级用户)
CREATE EXTENSION IF NOT EXISTS pg_prewarm;

-- 将 public.orders 表全部装入共享缓冲区
SELECT pg_prewarm(
    'public.orders',  -- 关系名
    'buffer',         -- 预热模式:直接进共享缓冲区
    'main',           -- 缓冲池:默认主池
    NULL,             -- 起始块:从开头
    NULL              -- 结束块:到结尾
);

如果只希望预热前一千个数据块,可以把起始和结束块明确写出来,这在超大表部分预热时能显著缩短执行时间并降低对内存的冲击。此外,对索引的预热语法完全一致,只需把关系名换成索引名,就能让索引页同样常驻内存,对依赖索引扫描的查询帮助明显。

执行该函数要求调用者对该关系具有查询权限,且将页面读入共享缓冲区需要数据库有足够空闲缓冲槽,否则较旧的页面会被替换出去。因此在内存紧张的实例上,应当挑选真正热点的表来预热,而不是盲目加载全部库表。

自动预热机制与配置实践

要让PostgreSQL在重启后自动恢复缓冲区状态,首先必须在postgresql.conf里把pg_prewarm加入shared_preload_libraries,并置pg_prewarm.autoprewarm = on。数据库启动阶段会启动一个叫做autoprewarm master的辅助进程,它负责在实例关闭前由普通后台进程记录缓冲页,在启动后按记录重新加载。记录文件默认放在pg_prewarm自动管理的路径下,内容是所有需要预热的表空间、数据库、关系及块号列表。

以下是最简配置片段:

# postgresql.conf 相关配置
shared_preload_libraries = 'pg_prewarm'
pg_prewarm.autoprewarm = on
pg_prewarm.autoprewarm_interval = 300   # 每五分钟转储一次缓冲页记录

配置完成后重启实例,系统会自动在后台完成预热,无需人工干预。不过自动预热并非银弹:它只能恢复重启前已经在内存中的页面,如果某张表在重启前从未被访问过,自动预热也不会将其加入。同时,若实例共享缓冲区设置很小,而记录文件覆盖了远超缓冲区容量的页面,启动时会出现大量页面竞争,反而拖慢初始连接。

从运维角度看,建议把自动预热作为兜底手段,再配合监控脚本观察pg_buffercache视图中的命中率变化。当发现核心表未命中率偏高时,可临时用手动函数补充预热,从而在稳定性与灵活性之间取得平衡。

预热效果观察与常见误区

验证pg_prewarm是否生效,最直接的方法是查询pg_buffercache扩展提供的视图,确认目标关系的页面在bufferid中大量出现,同时观察pg_stat_database里的blks_read在预热后查询中不再快速增长。也可以对比预热前后同一条复杂查询的执行计划与耗时,通常首轮时间会有数量级下降。

一个常见误区是认为pg_prewarm能把数据永久钉在内存中。实际上共享缓冲区遵循淘汰算法,如果预热后实例持续面临其他大查询,之前预热的页面仍可能被换出。因此预热不是一劳永逸的操作,而是应当嵌入到运维节奏里,比如每天业务高峰前定时跑一次手动预热脚本。

另一个误区是忽略操作系统缓存层。使用prefetchread模式时,页面可能只进入操作系统页缓存而未进数据库共享缓冲区,此时虽然减少了数据库自己管理的物理读,但仍有从OS缓存拷贝到共享缓冲的开销。在对延迟极度敏感的场景,应优先选择buffer模式并确认共享缓冲区尺寸充足。

pg_prewarmPostgreSQLbuffer_cache修改时间:2026-08-14 16:09:31

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。