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

时间:2017-01-29 01:16:17

标签: postgresql logging prepared-statement plpgsql sql-execution-plan

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

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

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

因为这样可以更容易地复制/粘贴查询以在另一个终端中重现它,特别是如果查询有许多参数。

1 个答案:

答案 0 :(得分:1)

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

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

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

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

chapter "Plan Caching" in the manual中的详细信息。

您可以通过简单的演示观察效果。在同一个会话中(不一定是同一个交易):

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

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

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 > $1)

因此,您可以在当前会话的前几次调用中使用参数值 inlined 获取查询。

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

  

此外,对于通过EXECUTE执行的命令,还有无计划缓存。   相反,每次运行语句时都会计划命令。   因此,可以在函数内动态创建命令字符串   对不同的表和列执行操作。

当然,这实际上会影响表现。

相关: