7.5 参数、缓存计划与计划漂移
同一 query shape 可能面对完全不同参数选择率。每次用具体值规划可得到针对性路径,却支付 planning 成本;复用 generic plan 可省 planning,却看不到具体参数。缓存计划是成本取舍,不是“prepared statement 必然更快”。
7.5.1 自定义计划与通用计划
custom plan 把本次参数代入后规划,可使用 MCV、partition bounds 等具体信息;generic plan 保留 $1,适合参数分布相近或 planning 昂贵的重复语句。
在 plan_cache_mode=auto 下,prepared statement 前五次使用 custom plan;之后服务器比较这些 custom plan 的平均估算成本与 generic plan 成本,决定是否复用 generic。这个启发式比较的是 estimated cost,也不包含重新规划本身的全部现实收益。force_custom_plan / force_generic_plan 适合诊断对照,不应在没有 workload 证据时全局强制。
prepared statement 是 session 对象。DDL、统计变化和影响解析/规划的设置可触发 re-plan;search_path 变化也会重新解析。transaction pooling 下 client 与 server session 生命周期不同,driver/Pgbouncer 的 prepared statement 支持与配置必须单独验证,不能从裸 PostgreSQL session 外推。
7.5.2 预备语句、数据倾斜与参数敏感
fixture:
tenant 1 = 90000 rows
tenant 2..1001 = 10 rows each
index(tenant_id)强制 custom:
hot: estimate=90000 actual=90000 → 实测 Seq Scan
cold: estimate=10 actual=10 → 实测 Index Scan强制 generic:
estimate=100 for both
hot actual=90000
cold actual=10具体 node type 受表宽、cache、cost constants 与版本影响,不作为硬断言;真正的参数敏感证据是 custom estimate 能区分 90000/10,而 generic 必须使用同一估计。hot generic 路径即使本次仍足够快,也已经暴露风险:平均延迟可能掩盖少数大 tenant 的尾延迟。
处理方案按证据选择:
- 保持 auto,并观察 generic/custom 计数与参数分布;
- 对真正参数敏感的 workload 分 query shape 或显式选择策略;
- 改 schema/index/partition,使不同选择率下都可接受;
- 对 hot tenant 单独路由/批处理;
- 局部 force custom,并量化 planning 开销。
不要把 tenant literal 拼进 SQL 来“骗 custom plan”;这会扩大 query shape、失去安全参数绑定并污染统计。
7.5.3 计划变化是症状,不自动等于回归
计划会因以下因素合理变化:
数据量/分布与 ANALYZE sample
参数值与 custom/generic 决策
index/constraint/partition/schema
planner GUC/cost/JIT/parallelism
PostgreSQL/extension 版本
relation page/visibility/correlation回归判断顺序:
- result contract 是否仍正确;
- 同 workload 的 latency/throughput/resource/SLO 是否变差;
- wait 还是 executor 在耗时;
- estimate/actual 从哪里开始偏;
- 数据、statistics、settings 与参数是否可比;
- 新 plan 是否只是节点不同但成本更好;
- 改动是否增加写放大、WAL、memory 或尾延迟。
对计划做 canonical fingerprint 可以帮助发现变化,但不能把完整 JSON bytes 当稳定 API;版本会新增字段,cost/time 天生动态。保留原始计划,同时抽取 query identity、node responsibilities、cardinality error、buffers/spill/WAL 与环境 facts。
应急时可以用 planner GUC 证明替代路径,长期方案仍要回到统计、SQL、index、参数策略或版本 bug。第 8 章会把这里的计划证据放进慢查询闭环,第 9 章再审查 index 收益和写成本。
上一节:分区裁剪的两种时机 · 返回本章目录 · 下一节:建立计划证据基线 · 查看全书目录 · 查看索引中心