登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
导读
排行榜
资讯
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
写记录
写博客
小组
VIP申请
VIP网盘
网盘
联系我们
发帖说明
道具
勋章
任务
淘帖
动态
分享
留言板
导读
设置
我的收藏
退出
腾讯QQ
微信登录
1
2
/ 2 页
下一页
返回列表
首页
›
业界区
›
安全
›
为什么PostgreSQL不自动缓存执行计划?这可能是最硬核的 ...
为什么PostgreSQL不自动缓存执行计划?这可能是最硬核的优化解读
[ 复制链接 ]
锷稠
2025-9-25 21:11:07
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
为什么PostgreSQL不自动缓存执行计划?这可能是最硬核的优化解读
前言
在数据库性能方面,查询语句的执行计划是最关键的因素之一。每当数据库接收到一个查询时,它必须决定如何以最有效的方式执行该查询。这个决策过程——称为
执行计划
。 计算并生成最优的执行计划在时间上可能非常昂贵,尤其是对于经常执行的查询语句。为了减轻这种开销,数据库采用
执行计划缓存
(Oracle和SQL Server都会自动缓存执行计划)来解决这个问题,使它们能够重用先前计算的执行策略,而不是每次执行时都重新计算执行计划。
然而,执行计划缓存的工作方式在不同的数据库系统之间可能存在显著差异。PostgreSQL 对执行计划缓存采用了一种更加动态和自适应的方法,而 SQL Server 默认则会积极缓存所有语句的执行计划,从而导致性能上的巨大差异。
这里会深入探讨 PostgreSQL 如何处理执行计划缓存,并将它与 SQL Server 进行比较,以及如何在针对这两个数据库进行性能优化。然后还将讨论预处理语句、函数缓存、通用与自定义执行计划,以及两个数据库中的常见性能陷阱。
PostgreSQL 如何缓存执行计划
PostgreSQL 并不会自动缓存SQL 语句的执行计划。每次执行SQL 查询(如 SELECT、INSERT、UPDATE 或 DELETE)时,PostgreSQL 都会从头开始解析、优化生成执行计划并执行该查询。
这一行为与 SQL Server 大相径庭,但是后者默认会全局缓存执行计划。虽然这看起来一开始是一个劣势,但实际上,这使得 PostgreSQL 在数据分布随时间变化的动态环境中能够做出更好的执行计划优化决策。然而,PostgreSQL 确实会在某些情况下缓存执行计划,包括prepare预处理语句和 PL/pgSQL 函数。
预处理语句和查询计划缓存
在 PostgreSQL 中如果要使用执行计划缓存,可以使用预处理语句。预处理语句允许 PostgreSQL 缓存查询的执行计划,这样每次执行查询时就不需要重新编译它。
PREPARE get_users (INT) AS
SELECT * FROM users WHERE age > $1;
EXECUTE get_users(30);
复制代码
在上面例子中:
第一次调用 PREPARE 语句时,PostgreSQL 解析并规划查询。
当 EXECUTE 执行时,会重用缓存的执行计划,从而避免了额外的解析和规划开销。
自定义执行计划 vs. 通用执行计划
默认情况下,PostgreSQL 从自定义执行计划开始——该执行计划针对特定的参数值进行了优化。然而,如果一个prepare预处理语句被多次执行(通常是5次或更多次),PostgreSQL 会评估是否应该切换到通用执行计划。自定义执行计划是根据实际的参数值进行优化的,并且可能使用索引扫描、顺序扫描或其他优化的执行路径,这取决于数据的分布情况。
另一方面,通用执行计划是没有特定参数值的,而是依赖于来自 pg_statistic 的表统计信息来估算行的基数/选择性。这种方法消除了每次执行时的执行计划生成开销,但如果数据分布不均匀(数据倾斜),可能会导致查询使用的执行计划不佳。
PL/pgSQL 函数和执行计划缓存
PostgreSQL 还会在 PL/pgSQL 函数中缓存执行计划。当函数包含SQL语句时,PostgreSQL 在第一次执行后会缓存执行计划。
CREATE FUNCTION get_users_by_age(age_limit INT)
RETURNS SETOF users AS $$
BEGIN
RETURN QUERY SELECT * FROM users WHERE age > age_limit;
END;
$$ LANGUAGE plpgsql;
复制代码
第一次运行该函数时,PostgreSQL 会为 SELECT 语句创建一个缓存的执行计划。如果该函数被频繁调用,PostgreSQL 可能会像处理预处理语句一样切换到通用执行计划。为了控制这一行为,PostgreSQL 允许开发人员手动强制指定缓存策略:
ALTER FUNCTION get_users_by_age SET plan_cache_mode = 'force_custom_plan';
ALTER FUNCTION get_users_by_age SET plan_cache_mode = 'force_generic_plan';
复制代码
理解索引下的执行计划行为
PostgreSQL 决定使用自定义执行计划还是通用执行计划的一个主要因素是索引选择性。如果某个字段具有高基数(有很多唯一值),通常使用索引扫描是最佳选择。然而,如果某个字段具有低基数(唯一值较少),顺序扫描可能更高效。例如,考虑以下情况:
CREATE INDEX idx_users_age ON users(age);
复制代码
如果大多数年龄值分布均匀,PostgreSQL 可能更倾向于使用通用执行计划,因为参数变化对执行时间的影响不大。然而,如果某些值出现频率较高(例如:年龄 = 25 占据了表 60% 的行数),使用自定义执行计划将更有效。
总结
理解执行计划缓存的工作原理对于数据库性能调优至关重要。PostgreSQL 采取动态方法,避免了
参数嗅探
的陷阱,但需要明确配置以实现执行计划的重用。另一方面,SQL Server 激进地缓存执行计划,这可以减少每次执行计划生成的开销,但当参数值变化较大时,可能会引发
参数嗅探
问题。
对于从 SQL Server 转向 PostgreSQL 的开发人员,适应 PostgreSQL 的执行计划缓存行为可能需要一些时间。然而,通过谨慎使用prepare预处理语句、函数和
plan_cache_mode
参数设置,开发人员可以精细调优 PostgreSQL,以实现最佳性能。
本文版权归作者所有,未经作者同意不得转载。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
为什么
PostgreSQL
自动
缓存
执行
相关帖子
为什么说 C# 14 的 extension 扩展成员和 field 关键字不只是语法糖?
分享 5 种 .NET 桌面应用程序自动更新解决方案
我用 SubAgent 做了一个 AI 自动修复闭环:流式修代码、自动构建、失败重试
Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接
Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接
Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接
为什么我建议前端基建有必要做 npm 仓库私有化
为什么全国人民都能秒开同一个视频?
愿力为王:AI时代,为什么“执行力”不再重要
愿力为王:AI时代,为什么“执行力”不再重要
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
业界
为什么说 C# 14 的 extension 扩展成员和 field 关键字不只是语法糖?
0
426
腥狩频
2026-03-29
业界
分享 5 种 .NET 桌面应用程序自动更新解决方案
0
1003
寥唏
2026-03-30
安全
我用 SubAgent 做了一个 AI 自动修复闭环:流式修代码、自动构建、失败重试
0
783
挽幽
2026-03-30
业界
Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接
0
807
诸婉丽
2026-03-30
业界
Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接
0
904
訾懵
2026-03-30
业界
Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接
0
192
归悦可
2026-03-30
业界
为什么我建议前端基建有必要做 npm 仓库私有化
0
494
滕佩杉
2026-03-30
代码
为什么全国人民都能秒开同一个视频?
0
5
尤晓兰
2026-03-31
安全
愿力为王:AI时代,为什么“执行力”不再重要
0
837
陆菊
2026-03-31
安全
愿力为王:AI时代,为什么“执行力”不再重要
0
110
句惫
2026-03-31
回复
(32)
后彼
2025-10-25 01:13:23
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
热心回复!
揭荸
2025-11-26 20:11:13
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
不错,里面软件多更新就更好了
郏琼芳
2025-11-28 15:00:40
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
这个有用。
诘琅
2025-12-11 14:33:26
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
这个有用。
龙骋唧
2025-12-27 15:38:32
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
这个有用。
癖艺泣
2026-1-1 03:43:26
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢,下载保存了
赐度虻
2026-1-13 21:39:10
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
新版吗?好像是停更了吧。
乳杂丫
2026-1-15 17:58:28
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
不错,里面软件多更新就更好了
戟铵腴
2026-1-19 04:06:36
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
新版吗?好像是停更了吧。
常士
2026-1-19 04:22:21
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
yyds。多谢分享
揉幽递
2026-1-20 23:36:28
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢分享,学习下。
韦逸思
2026-1-21 10:09:51
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢分享,下载保存了,貌似很强大
距佰溘
2026-1-24 11:46:21
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
感谢,下载保存了
訾懵
2026-1-26 06:44:54
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
东西不错很实用谢谢分享
晌集涟
2026-1-27 03:28:15
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
收藏一下 不知道什么时候能用到
锦惺
2026-1-29 07:40:46
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
感谢发布原创作品,程序园因你更精彩
左丘平莹
2026-1-30 02:31:04
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
谢谢楼主提供!
舒菀菀
2026-2-4 06:41:11
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
东西不错很实用谢谢分享
氛疵
2026-2-4 12:11:17
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
这个有用。
下一页 »
1
2
/ 2 页
下一页
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
浏览过的版块
业界
签约作者
程序园优秀签约作者
发帖
锷稠
2026-2-4 12:11:17
关注
0
粉丝关注
15
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
3934307807
991125
anyue1937
9994892
kk14977
6845359
4
xiangqian
638210
5
神泱
9537
6
宋子
9883
7
韶又彤
9911
8
诀锺
9036
9
荪俗
9020
10
蓬森莉
9871
查看更多
今日好文热榜
6
host怎么设置,host设置教程
245
2026国内图床深度选型指南:从需求到实测,
874
Claude Code源码泄露:8大隐藏功能曝光
674
没有技术要求,只需5步就能完成数据分析和
388
完整项目实战
764
Python 数据类型:数字、字符串与容器
823
从“救火”到“预判”:AIOps 如何用 AI 重
598
Redis 单线程真的是单线程吗?源码角度全面
426
突发!Claude Code 51万行源码全网裸奔:一
495
使用 OpenSpec + 提示词工程 + Harness 思
528
.NET 进阶之路:异步、并发与内存管理的系
497
Java 中的 实现、泛型
977
Go + Vue 接入行为验证码完整指南
624
Python 面向对象编程:从入门到实践
766
Python 面向对象编程:从入门到实践
540
Mem0:给 AI Agent 装上「长期记忆」
757
Mem0:给 AI Agent 装上「长期记忆」
632
我用 Codex 和 Gemini,做了一个本地桌面版
428
Go + Vue 接入行为验证码完整指南
510
Mem0:给 AI Agent 装上「长期记忆」