IMMUTABLE、STABLE 和 VOLATILE 关键字如何影响函数的行为?

问题描述 投票:0回答:1

我们编写了一个函数

get_timestamp()
定义为

CREATE OR REPLACE FUNCTION get_timestamp()
  RETURNS integer AS
$$
SELECT (FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 10) - 13885344000)::int;
$$
LANGUAGE SQL;

这用于插入和更新,以在数据库记录中创建和修改的字段中输入或编辑值。但是,我们发现当连续添加或更新记录时,它返回相同的值。

在检查 pgAdmin III 中的函数时,我们注意到在运行 SQL 来构建函数时,关键字 IMMUTABLE 已在 LANGUAGE SQL 语句之后注入。 documentation指出默认是VOLATILE(如果这些都没有出现,则VOLATILE是默认假设),所以我不确定为什么注入IMMUTABLE,但是,将其更改为STABLE解决了重复值的问题。

注意:如已接受的答案中所述,IMMUTABLE 永远不会由 pgAdmin 或 Postgres 添加到函数中,而必须在开发过程中添加。

我猜测正在发生的事情是这个函数正在被评估并且结果被缓存以进行优化,因为它被标记为 IMMUTABLE 指示 Postgres 引擎在给定相同(空)参数列表的情况下返回值不应更改。但是,当不在触发器中使用时,当直接在 INSERT 语句中使用时,该函数将返回不同的值五次,然后再返回相同的值。这是由于某些优化算法所说的“如果在会话中使用 IMMUTABLE 函数超过 5 次,则缓存结果以供将来调用”之类的内容吗?

任何关于如何在 Postgres 函数中使用这些关键字的澄清将不胜感激。鉴于我们在触发器中使用此函数,STABLE 对我们来说是正确的选择吗?还是还有更多需要考虑的事情,例如文档说:

(对于希望查询行的 AFTER 触发器来说是不合适的 由当前命令修改。)

但我不太清楚为什么。

database postgresql function timestamp volatility
1个回答
10
投票

关键字

IMMUTABLE
是由 pgAdmin 或 Postgres 自动添加的 never。创建或替换该函数的人就是这么做的。

给定函数的正确波动性

VOLATILE
(也是默认值),而不是
STABLE
- 否则使用
clock_timestamp()
是没有意义的,即
VOLATILE
now()
CURRENT_TIMESTAMP
相比,它们是
STABLE
:它们在同一事务中返回相同的时间戳。 说明书:

clock_timestamp()
返回实际的当前时间,因此其 即使在单个 SQL 命令中,值也会发生变化。

所以,不是

STABLE

手册警告函数波动性
STABLE
...

不适用于希望查询已修改行的

AFTER
触发器 通过当前命令。

...因为它会期望在同一个语句中得到相同的结果并优化另一个查找。

你问:

您是否知道该函数为何正确返回 5 设置为

IMMUTABLE
时,坚持第五个值之前的次数?

Postgres Wiki

在 9.2 中,规划者将使用有关以下方面的具体计划: 发送的参数(查询将在执行时计划),除非 查询被执行了几次并且规划者决定 通用计划并不比特定计划贵太多。

我的粗体强调。对于没有输入参数的

IMMUTABLE
函数似乎没有意义。但是错误标签被主体中的
VOLATILE
函数覆盖(无效 函数内联):不同的查询计划仍然有意义。 相关:

旁白

trunc()
floor()
稍快,并且在这里执行相同的操作,因为保证为正数:

SELECT (trunc(EXTRACT(EPOCH FROM clock_timestamp()) * 10) - 13885344000)::int
© www.soinside.com 2019 - 2024. All rights reserved.