如何使用内联参数值在 PLPGSQL 中记录查询

How to log queries inside PLPGSQL with inlined parameter values

当我的 PLPGSQL 函数 (Postgres 9.6) 中的语句被 运行 时,我可以在一行中看到查询,然后在另一行中看到所有参数。一个 2 行日志记录。类似于:

LOG:  execute <unnamed>: SELECT * FROM table WHERE field1= AND field2= ...    
DETAIL:  parameters:  = '-767197682',  = '234324' ....

是否可以将整个查询记录在 pg_log WITH 查询中已替换的参数并将其记录在 SINGLE 行?

因为这将使 copy/paste 查询更容易在另一个终端中重现它,尤其是当查询有几十个参数时。

这背后的原因:PL/pgSQL 在内部将 SQL 语句视为 准备语句

首先:在默认设置下,没有记录PL/pgSQL函数中的SQL语句全部。您在使用 auto_explain 吗?

同一会话中的前几次调用,SPI 管理器(服务器编程接口)根据实际 参数值生成新的执行计划。任何类型的日志记录都应报告参数值 inline.

Postgres 会跟踪并在当前会话中进行几次调用后,如果执行计划似乎对实际参数值不敏感,它将开始重新使用通用的缓存计划。然后你应该看到带有 $n 参数的准备好的语句的通用计划(就像在问题中一样)。

详情在chapter "Plan Caching" in the manual.

你可以通过一个简单的demo来观察效果。在同一会话中(不一定是同一笔交易):

CREATE TEMP TABLE tbl AS
SELECT id FROM generate_series(1, 100) id;

PREPARE prep1(int) AS
SELECT min(id) FROM tbl WHERE id > ;

EXPLAIN EXECUTE prep1(3);  -- 1st execution

您将看到实际值:

  Filter: (id > 3)
EXECUTE prep1(1);  -- several more executions
EXECUTE prep1(2);
EXECUTE prep1(3);
EXECUTE prep1(4);
EXECUTE prep1(5);

EXPLAIN EXECUTE prep1(3);

现在您将看到一个 $n 参数:

  Filter: (id > )

因此您可以在当前会话的前几次调用中获得参数值 内联 的查询。

或者您可以将动态 SQL 与 EXECUTE 一起使用,因为 per documentation:

Also, there is no plan caching for commands executed via EXECUTE. Instead, the command is always planned each time the statement is run. Thus the command string can be dynamically created within the function to perform actions on different tables and columns.

当然,这实际上会影响性能。

相关: