发布时间:2026/9/4 0:20:59
PostgreSQL 计划缓存实战(第 10 篇):预编译 SQL 前五次都快,第六次为什么可能变慢 普通租户只有百条订单头部租户却有九十万条。相同 prepared statement 前几次都快某个连接复用后头部租户突然用索引扫描九十万行重连又恢复。直接答案是这个会话可能在累计五个 custom plan 后开始评估 generic plan而 generic plan 看不到本次参数冷热租户差异便被平均分布掩盖。Custom plan 看得到本次参数generic plan 省掉重复规划却只能按平均分布估算。参数倾斜越强省下的规划毫秒越可能换来执行秒级退化。先纠正“第六次必切换”plan_cache_mode auto时PostgreSQL 对带参数的 prepared statement 前五次使用 custom plan并计算其平均估算成本之后生成 generic plan将其成本与平均 custom 成本比较。如果重复规划看起来不值得后续才使用 generic plan。因此第六次是开始具备选择 generic 的条件不是必然切换最终可能继续 customDDL、统计更新等会触发重新分析/规划每个数据库会话拥有自己的 prepared statement 与计数历史。源码证明比较的不是前五次真实耗时PostgreSQL 18.6 的核心入口位于src/backend/utils/cache/plancache.c的choose_custom_plan()。去掉强制模式、一次性计划等前置分支后决策等价于# 逻辑等价伪代码不是可编译源码 num_custom_plans 5 → custom avg_custom_cost total_custom_cost / num_custom_plans generic_cost avg_custom_cost → generic 其他情况 → custom这里有两个容易写错的细节比较的是 planner 的估算成本不是前五次的真实执行时间custom cost 会计入重复规划的估算开销generic cost 不计每次重规划因此 generic 只要在“执行估算 重规划代价”的总账上更便宜就可能胜出。第一次尝试 generic 时generic_cost尚未确定代码会先构建 generic plan、记录成本再调用一次choose_custom_plan()复核如果 custom 一直明显占优这个刚生成的 generic plan 不会被实际执行。因此“第六次开始评估”比“第六次执行 generic”更准确。PREPARE/EXECUTE → GetCachedPlan() → choose_custom_plan() → num_custom_plans、total_custom_cost、generic_cost → custom 或 generic → pg_prepared_statements.generic_plans/custom_plans本文不补无关 Java 示例要证明的是 PostgreSQL 服务端计划缓存决策SQLPREPARE/EXECUTE是最直接入口。JDBC 驱动的 server-side prepare 阈值属于调用前置条件必须在生产排查时另行确认不能代替服务端证据。构造冷热租户DROPTABLEIFEXISTStenant_order;CREATETABLEtenant_order(idbigintPRIMARYKEY,tenant_idbigintNOTNULL,payloadtextNOTNULL);-- 热租户 1900000 行INSERTINTOtenant_orderSELECTg,1,repeat(h,100)FROMgenerate_series(1,900000)ASg;-- 1000 个冷租户每个约 100 行INSERTINTOtenant_orderSELECT900000g,2((g-1)%1000),repeat(c,100)FROMgenerate_series(1,100000)ASg;CREATEINDEXtenant_order_tenant_idxONtenant_order(tenant_id);ANALYZEtenant_order;PREPAREtenant_q(bigint)ASSELECTsum(length(payload))FROMtenant_orderWHEREtenant_id$1;先做确定性对照SETplan_cache_modeforce_custom_plan;EXPLAIN(ANALYZE,BUFFERS,SETTINGS)EXECUTEtenant_q(2);EXPLAIN(ANALYZE,BUFFERS,SETTINGS)EXECUTEtenant_q(1);SETplan_cache_modeforce_generic_plan;EXPLAIN(ANALYZE,BUFFERS,SETTINGS)EXECUTEtenant_q(2);EXPLAIN(ANALYZE,BUFFERS,SETTINGS)EXECUTEtenant_q(1);Custom plan 对冷租户通常适合索引路径对 90% 行都命中的热租户可能选择顺序扫描。Generic plan 中会保留$1无法知道这次是头部租户可能按平均每租户行数选择索引路径导致热参数大量随机/重复 heap 访问。实际计划取决于缓存、成本参数和数据宽度。这个实验的判定不是强求某个节点而是比较同一参数在 custom/generic 下的行数估算、Buffers 与耗时。恢复自动模式重新准备以清空该语句的计划历史DEALLOCATEtenant_q;SETplan_cache_modeauto;PREPAREtenant_q(bigint)ASSELECTsum(length(payload))FROMtenant_orderWHEREtenant_id$1;EXECUTEtenant_q(2);EXECUTEtenant_q(3);EXECUTEtenant_q(4);EXECUTEtenant_q(5);EXECUTEtenant_q(6);EXPLAIN(ANALYZE,BUFFERS,SETTINGS)EXECUTEtenant_q(1);SELECTname,generic_plans,custom_plans,statementFROMpg_prepared_statementsWHEREnametenant_q;前五次全是冷租户会影响平均 custom 成本第六次热参数可能遇到 generic也可能算法仍判定 custom 更好。generic_plans/custom_plans是事实证据不能仅凭“恰好第六次慢”倒推。还应记录同一次观察前后的计数差而不是只看最终总数SELECTname,generic_plans,custom_plansFROMpg_prepared_statementsWHEREnametenant_q;EXPLAIN(ANALYZE,BUFFERS,SETTINGS)EXECUTEtenant_q(1);SELECTname,generic_plans,custom_plansFROMpg_prepared_statementsWHEREnametenant_q;若generic_plans增加说明这次取得了 generic plan若只看到$1也应与计数交叉验证避免把展示差异当成完整会话历史。为什么连接池让故障像随机事件Prepared statement 是 session 对象。连接池中的每个后端经历不同参数序列连接 A冷、冷、冷、冷、冷 → generic → 热参数退化 连接 B热、热、冷、热、冷 → custom 平均成本不同 连接 C刚重建连接 → 重新从 custom 开始应用日志看到同一 SQL数据库看到的是多份会话级计划历史。pg_prepared_statements也只显示当前会话可见对象不能从一个管理连接观察整个池。还要确认驱动是否真的创建 server-side prepared statement、准备阈值是多少、事务池化是否保留 session以及代理是否改写连接语义。客户端叫“预编译”不自动等于 PostgreSQLPREPARE。四种处理路径路径适用条件代价与边界保持auto参数分布较均匀规划成本值得节省极端热点可能被平均值掩盖局部force_custom_plan参数强烈决定路径、单次执行较重每次支付规划 CPU拆分冷热 SQL/连接热租户可稳定识别应用路由与观测复杂度上升索引、分区或模型治理倾斜是长期业务事实变更成本高但可能根治访问路径不要全局强制 custom。高 QPS、执行极短的语句可能把大量 CPU 浪费在重复规划也不要用DEALLOCATE或重连作为长期修复它只重置历史退化可能再次出现。生产证据链在同一会话、同一参数下分别强制 custom/generic比较计划与执行。看$1是否仍出现在计划中结合generic_plans/custom_plans确认类型。找第一处 estimated/actual rows 分叉确认租户热点是否进入统计。核对驱动、连接池、代理和 prepared threshold。用pg_stat_statements比较 calls、planning/execution time 与波动但注意它不会直接替代会话级计划证据。在真实参数分布和并发下计算“规划 CPU 执行成本”的总账。如果第一处分叉来自列相关性或数据分布估错先阅读第 9 篇SQL 和索引没变计划为什么突然慢一百倍修复统计证据计划缓存不能替代基数估算治理。灰度与回滚优先对专用报表角色、事务或单个连接设置BEGIN;SETLOCALplan_cache_modeforce_custom_plan;-- 目标查询COMMIT;灰度记录热/冷参数 p95、规划 CPU、数据库总 CPU 和连接池吞吐。若规划时间或整体 CPU 超过停止阈值停止扩大范围。恢复auto可撤销设置但不能自动修复数据倾斜和索引模型。证据边界证据能证明不能证明第六次变慢与启发式时点吻合一定已经切 generic计划中出现$1当前展示的是 generic plan所有连接都使用 generic强制 custom 更快参数感知对该值有收益全局 custom 总成本更低重连恢复session 状态参与故障根因只有 plan cache统计显示热点planner 有热点信息generic 能使用本次参数值面试表达主线Prepared statement 可以用参数感知 custom plan也可复用 generic plan。Auto 前五次采样 custom 成本之后比较 generic 与平均 custom 成本并非第六次必切。参数倾斜时要在同一会话对比两类计划并结合驱动、连接池和规划 CPU 做局部治理。实验清理DEALLOCATEtenant_q;RESET plan_cache_mode;DROPTABLEIFEXISTStenant_order;官方资料PostgreSQL 18PREPAREPostgreSQL 18plan_cache_modePostgreSQL 18pg_prepared_statementsPostgreSQL 18EXPLAINPostgreSQL 18.6 源码plancache.c / choose_custom_plan()PostgreSQL 18.6 源码标签 REL_18_6

相关新闻

2026/9/4 0:20:59

快速舞蹈视频补帧全指南:从FFmpeg到RIFE实战优化

之前在整理一段节奏很快的舞蹈素材时,我遇到一个很典型的困惑:原视频帧率只有 30fps,角色或舞者一旦快速下叉、甩腿、左右摆动,画面就会明显发虚,甚至能感觉到“一卡一卡”的拖影。后面尝试用补帧(Frame In…

2026/9/4 0:20:59

端侧AI的价值真相:从模型效率到硬件部署的工程挑战

端侧AI到底有没有价值,这个问题的答案,正在从“技术趋势”变成“资本问题”。面壁智能冲刺上市,让这件事变得更有意思:当一家以“小模型高效率”为路线的AI公司走进二级市场视野,它真正需要回答的,不是“参…

2026/9/4 0:20:59

手机变身探测器:SweepLED用AI分析反光定位隐藏摄像头

如果你需要在房间里快速排查隐藏摄像头,SweepLED 是一个很值得关注的检测思路:它来自 KAIST 相关研究团队,核心做法是把智能手机自带的屏幕光源变成主动照明设备,再利用 AI 分析摄像头画面中的反光特征,帮你定位可疑的…

2026/9/4 1:11:04

解析split与mph:用Python构建运动速度曲线分析模型

先跑一段速度数据,看看自己到底能榨出多少信息。最近我在处理运动表现数据时,拿到一组类似「2.88 split / 31.21 mph」的记录,一开始只觉得是一个分段计时和瞬时速度,真正动手做转换、建模、可视化之后,才发现里面的门…

2026/9/4 1:11:04

Qt常用控件学习路线:理解对象树与信号槽,手写界面代码

重学 Qt 的第二站,几乎都会落在常用控件上。Qt 自带的控件种类远不止 QPushButton、QLabel 这几样,但如果只是逐个控件试属性,学完两周后很容易发现自己只是记住了 API 名,遇到一个带输入框、下拉框和表格的窗口仍然不知道代码该怎…

2026/9/4 1:11:04

Matlab仿真椭圆振动铣削:从轨迹规划到超声加工应用

简介:本资源面向机械制造、超声加工及先进切削工艺领域的研究生、工程师与科研人员,聚焦椭圆振动铣削这一融合超声技术与传统铣削的高精度加工方法,解决难加工材料切削力大、表面质量差、刀具磨损快等工程痛点。压缩包共2个文件(1…

2026/9/4 1:11:04

MATLAB森林火灾检测实战:构建抗干扰鲁棒工作流

简介:本资源是一套基于图像处理技术的森林火灾检测Matlab实现方案,面向计算机、电子信息工程、数学等专业的本科生,适用于课程设计、期末大作业及毕业设计等实践教学场景,解决真实环境下的火焰与烟雾识别问题。压缩包共18个文件&a…

2026/9/4 1:06:03

AI电话外呼工具有哪些?AI初筛+真人坐席如何守住B24合规

【数据截止日期:2026年9月3日】【作者资质说明:本文作者为通信行业独立观察者,拥有5年以上企业通信服务研究经验(作者自陈述,未附第三方资质证明),本文为第三方自媒体平台发布的行业科普内容&am…

2026/9/3 18:28:26

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/9/3 14:29:47

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/9/3 14:30:35

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/4 0:00:58

STM32H743 SPI从机DMA双缓冲通信实战

简介:本资源是面向嵌入式开发工程师与STM32进阶学习者的SPI DMA双机通信从机端完整实现方案,聚焦STM32H743高性能Cortex-M7单片机在工业控制与高速数据交互场景下的从机通信开发痛点。压缩包含1355个文件,主体为599个C源码与321个头文件&…

2026/9/4 0:00:58

CPU开盖降温教程:20元成本让温度直降30度的原理与实践

最近很多朋友都在抱怨,自己的电脑一到夏天就变成"烤箱",玩游戏时CPU温度动不动就飙到90度以上,风扇噪音堪比直升机。更让人头疼的是,明明配置不错,却因为高温降频导致性能大打折扣。如果你也遇到了类似问题&…

2026/9/4 0:00:58

ArkTS 表单工程:场地预约页的三态场次 Grid 与校验

ArkTS 表单工程:场地预约页的三态场次 Grid 与校验 App 14「运动场地预约」场地 Tab(Func1Tab),是整 App 交互最丰富的页面——场地横向切换 三色图例 渐变预约预览卡 快捷模板 今日场次 Grid(可选/已选/已满三态&…

2026/9/3 20:43:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/3 17:51:43

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/3 21:06:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…