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