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

我们写了一个函数get_timestamp()定义为

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

这用于INSERT和UPDATE在数据库logging的创build和修改字段中input或编辑一个值。 但是,我们发现当连续添加或更新logging时,它将返回相同的值。

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

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

我猜测发生了什么是这个函数正在被评估和结果被caching优化,因为它被标记为IMMUTABLE指示Postgres引擎返回值不应该改变给定相同(空)参数列表。 但是,如果不在触发器中使用,则直接在INSERT语句中使用时,函数将在返回相同的值之前返回一个不同的值FIVE次。 这是由于一些优化algorithm,如“如果一个IMMUTABLE函数在会话中多使用5次,caching未来调用结果”?

任何关于如何在Postgres函数中使用这些关键字的澄清,将不胜感激。 对于我们来说,STABLE是正确的select,因为我们在触发器中使用了这个函数,或者还有更多要考虑的地方,例如文档说:

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

但我为什么不清楚。

关键词IMMUTABLE 不会由pgAdmin或Postgres自动添加。 谁创造或取代了这个function呢。

给定函数的正确函数波动 (读手册)设置是VOLATILE ,而不是STABLE – 或者使用clock_timestamp()VOLATILE而不是now()CURRENT_TIMESTAMP ,它们被定义为STABLE : 根据文档 ,在相同的事务中返回相同的时间戳:

clock_timestamp()返回实际的当前时间,因此即使在一个SQL命令中,它的值也会改变。

该手册警告说 ,function波动STABLE

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

因为对同一行的触发函数的重复评估可以返回不同的结果。 所以, STABLE 。 我不认为那里甚至需要警告,因为它是相当明显的。

你问:

当设置为IMMUTABLE时,为什么函数返回正确五次,然后粘在第五个值上?

引用Postgres Wiki :

对于9.2,规划者将使用关于发送的参数(查询将在执行中计划)的具体计划,除非多次执行查询并且规划者决定通用计划并不比具体计划贵得多。

大胆重视我的。 对于IMMUTABLE函数来说似乎没有意义(也不会造成伤害),但是在可能的情况下使用VOLATILE函数仍然会触发初始重新计划。 (最后一点只是我的猜测。)
更多解释在这里:

  • PostgreSQL存储过程的性能

在旁边

trunc()floor()稍微快一些,因为正数保证:

 SELECT (trunc(EXTRACT(EPOCH FROM clock_timestamp()) * 10) - 13885344000)::int