gpt4 book ai didi

postgresql - 为什么 auto_explain 只在第一次调用 PL/pgSQL 函数时记录嵌套语句?

转载 作者:行者123 更新时间:2023-11-29 13:41:10 25 4
gpt4 key购买 nike

在我的 Postgres 服务器上,我使用 auto_explain 模块和 log_nested_statements 来记录 PL/pgSQL 函数中的其他函数调用。

594 session_preload_libraries = 'auto_explain'
595
596 auto_explain.log_min_duration = 0
597 auto_explain.log_nested_statements = true
598 auto_explain.sample_rate = 1.0

我有一个玩具 PL/pgSQL 函数 baz(count int):

Schema              | public
Name | baz
Result data type | text
Argument data types | count integer
Type | normal
Volatility | volatile
Parallel | unsafe
Owner | aerust
Security | invoker
Access privileges |
Language | plpgsql
Source code | +
| DECLARE +
| i int := 0; +
| result text := ''; +
| BEGIN +
| +
| IF (count < 1) THEN +
| RETURN result; +
| END IF; +
| +
| LOOP +
| EXIT WHEN i = count; +
| i := i + 1; +
| result := result || ' ' || foo();+
| END LOOP; +
| +
| RETURN result; +
| END; +
|
Description |

调用 SQL 函数 foo():

Schema              | public
Name | foo
Result data type | text
Argument data types |
Type | normal
Volatility | immutable
Parallel | unsafe
Owner | aerust
Security | invoker
Access privileges |
Language | sql
Source code | SELECT 'foo ' || bar()
Description |

在数据库连接中第一次调用函数 baz(1) 时,我看到每个嵌套语句都记录为计划的一部分:

2019-03-19 15:25:05.765 PDT [37616] LOG:  statement: select baz(1);
2019-03-19 15:25:05.768 PDT [37616] LOG: duration: 0.002 ms plan:
Query Text: SELECT 'bar'
Result (cost=0.00..0.01 rows=1 width=32)
2019-03-19 15:25:05.768 PDT [37616] CONTEXT: SQL function "bar" statement 1
SQL function "foo" during startup
SQL statement "SELECT result || ' ' || foo()"
PL/pgSQL function foo(integer) line 14 at assignment
2019-03-19 15:25:05.768 PDT [37616] LOG: duration: 0.001 ms plan:
Query Text: SELECT 'foo ' || bar()
Result (cost=0.00..0.01 rows=1 width=32)
2019-03-19 15:25:05.768 PDT [37616] CONTEXT: SQL function "foo" statement 1
SQL statement "SELECT result || ' ' || foo()"
PL/pgSQL function foo(integer) line 14 at assignment
2019-03-19 15:25:05.768 PDT [37616] LOG: duration: 0.952 ms plan:
Query Text: select baz(1);
Result (cost=0.00..0.26 rows=1 width=32)

但是,当我在同一连接上再次调用该函数时,我没有在日志中看到嵌套语句:

2019-03-19 15:29:06.608 PDT [37616] LOG:  statement: select baz(1);
2019-03-19 15:29:06.608 PDT [37616] LOG: duration: 0.046 ms plan:
Query Text: select baz(1);
Result (cost=0.00..0.26 rows=1 width=32)

这是为什么?以及如何在同一数据库连接期间将嵌套语句记录到该函数的后续调用中?

最佳答案

您可以这样做以每次都记录语句:

ALTER FUNCTION foo() STABLE;

但是这样你的表现会受到一点影响。

揭开谜底:

  • 在 PL/pgSQL 函数中调用的 SQL 语句的执行计划在数据库 session 的生命周期内被缓存,因此它们仅在函数首次执行时被解析一次。

  • IMMUTABLE 表达式在解析 SQL 语句时计算并转换为常量。

仅在第一次记录的语句是仅在解析 baz 中的 SQL 语句时才评估的语句。

关于postgresql - 为什么 auto_explain 只在第一次调用 PL/pgSQL 函数时记录嵌套语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55250925/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com