监控 Postgres 查询解析器

And*_*mar 6 postgresql execution-plan explain postgresql-9.1 plan-cache

据我了解,当您向 Postgres 发送查询时,例如:

SELECT id FROM table1 WHERE name = $1;
Run Code Online (Sandbox Code Playgroud)

Postgres 将创建一个查询计划。该计划将在同一个会话中为同一个查询缓存。但是如果你创建一个函数:

CREATE OR REPLACE FUNCTION get_table1 (parname text) RETURNS bigint
LANGUAGE plpgsql AS 
$$BEGIN
  RETURN (SELECT id FROM table1 where name = parname);
END$$;
Run Code Online (Sandbox Code Playgroud)

查询计划将为所有未来的会话缓存。

我想通过检查查询分析器的调用频率来验证这个理论。有没有办法检查 Postgres 解析查询的次数?

如果可能,我想监视每秒 #parses 和最小/最大/平均解析持续时间等内容。

Erw*_*ter 5

不可能保存“所有未来会话”的查询计划查询计划仅针对当前会话保存。并且只有在一些有利的条件下才能重复使用。

根本不保存临时 SQL 查询的计划。PL/pgSQL 函数内的所有查询都被视为准备好的语句。还有更多的步骤不仅仅是查询规划。

值得注意的是,自 Postgres 9.1 以来发生了重大变化,其中通用计划更普遍地保存并重用于 PL/pgSQL 中的语句。这在 9.2 pg 中变得更加智能。

手册(粗体强调我的):

准备好的语句仅在当前数据库会话期间持续。

这还没有说任何关于查询计划的事情

执行语句时,会解析、分析并重写PREPARE指定的语句 。当随后发出命令时,将计划并执行准备好的语句。EXECUTE

再往下:

如果准备好的语句被执行足够多次,服务器 最终可能会决定保存并重新使用通用计划,而不是每次都重新计划。如果准备好的语句没有参数,这将立即发生;否则,仅当通用计划似乎比取决于特定参数值的计划贵不了多少时,才会发生这种情况。通常,只有当估计查询的性能对所提供的特定参数值相当不敏感时,才会选择通用计划。

如何判断是否使用通用计划?

要检查 PostgreSQL 用于准备语句的查询计划,请使用EXPLAIN。如果使用通用计划,它将包含参数符号$n,而自定义计划将用当前实际参数值替换其中。

保存的计划始终是通用计划,但反之则不然。
准备好的语句保存在哪里?

您可以通过查询系统视图来查看会话中可用的所有准备好的语句pg_prepared_statements

PL/pgSQL 中 SQL 语句的查询计划

这些通常在EXPLAIN输出中不可见。您也可以安装附加模块自动解释来将这些计划写入日志。详细信息在这里:

有关PL/pgSQL 函数中计划缓存的详细信息,最好直接阅读手册。