详情

首页手游攻略 PostgreSQL 19 pg_plan_advice怎么用?查询计划建议入门

PostgreSQL 19 pg_plan_advice怎么用?查询计划建议入门

佚名 2026-11-02 11:50:01

一条SQL忽然变慢,可能是数据库改变了执行路线,例如先扫描的表换了,或由索引查询变成读整张表。19中的pg_plan_advice允许对其中一些选择给出明确建议,方便定位和改善计划问题。

既可以保存已验证的选择,也可以试验另一种方案。但控制得住不代表一定更快,数据分布或条件改变后,旧方案也可能不再合适。

一、查询计划是什么,为什么会变?

SQL说明要什么结果,执行计划安排先访问谁、用什么办法查询与关联。数据库会结合行数、统计信息、现有索引和成本设置作出选择。

计划发生变化不一定是坏事。表里只有几百行时,直接读完可能比走索引省事;增长到几百万行后,另一种方式才更合适。真正要处理的是:某条重要查询反复选到明显不合适的计划,已经影响业务。

处理顺序应该是先检查统计信息、索引和查询写法。若这些都处理过,仍有明确的计划问题,再考虑用 advice 限定某一部分选择。

二、它能控制什么,又不能控制什么?

常见可干预的内容包括扫描方式、表的关联顺序、关联算法和部分并行选择。比如可以对比先从哪张表开始,或者某个位置采用哪种关联方式。

它仍然是在原有优化器能考虑的范围里工作,不是另造一套执行器。一个索引根本不能满足这条查询,或者要求的计划不符合查询含义,写一条 advice 也无法把它变成正确可用的方案。

因此,要看 EXPLAIN 中的实际计划和建议反馈,而不是 SET 没报错就认为已经生效。

三、从当前计划开始,比手写复杂规则更稳妥

先确认安装包包含该模块,并由有相应权限的管理员在测试会话加载:

LOAD 'pg_plan_advice';

再让数据库输出当前计划及对应建议。下面的表和字段需要换成自己的业务对象:

EXPLAIN (COSTS OFF, PLAN_ADVICE)SELECT o.id, c.nameFROM public.orders oJOIN public.customers c ON c.id = o.customer_id;

输出中会出现 Generated Plan Advice。先理解当前计划,再只挑需要控制的部分。例如,想在实验中限定以 o、c 的顺序关联:

SET pg_plan_advice.advice = 'JOIN_ORDER(o c)';EXPLAIN (COSTS OFF)SELECT o.id, c.nameFROM public.orders oJOIN public.customers c ON c.id = o.customer_id;RESET pg_plan_advice.advice;

这里的 o、c 是查询中的别名。别名写错、查询结构变化,都可能导致建议没有匹配。测试后及时 RESET,避免规则影响同一连接里的后续查询。

四、怎么证明建议有用?

先保存不加建议时的计划和耗时,再加上建议运行同样的查询。需要真实执行数据时,使用 EXPLAIN ANALYZE;它会执行 SQL,应先在合适的测试环境使用。

至少测试常见条件、返回很少数据的条件,以及返回大量数据的条件。例如小客户与大客户的订单数量差别很大,只拿小客户测试出来的最佳计划,不一定适合大客户。

除了总时间,还要看读了多少数据、有没有临时文件、并发时是否挤占其他请求。建议反馈显示 matched,只说明建议匹配到了,并不等于性能一定更好。

五、pg_stash_advice 又是做什么的?

单独使用 pg_plan_advice,通常需要在会话中设置建议。pg_stash_advice 则可以把建议与查询标识对应保存,在后续生成该查询计划时自动应用,减少每次手动设置的工作。

这套功能需要单独配置与管理,不会因为装了19就让所有查询自动固定计划。管理员还要安排权限、建议的存储和使用范围。

每条上线建议都应记录对应查询、要解决的问题、负责人和复查时间。SQL或索引改变、数据增长明显后,要再测试,避免临时处理长期无人维护。

最适合采用它的情况,是已经有证据表明某个计划选择不理想,并能测出更好的方案。只限制必要的一小部分,通常比固定整条计划更好维护。

点击查看更多
推荐专题
热门阅读