IMMUTABLE | STABLE | VOLATILE
分别代表,非常稳定,稳定,不稳定。
稳定,函数不可以修改数据库的数据,同一个QUERY中,如果需要返回该函数的结果,那么将合并多次运算为一次这个函数(后面会有例子)。另外,只有stable和immutable的函数才可以被执行计划选择作为索引的比较条件。(因为索引比较时,被比较的值只运算一次.这个就需要stable和immutable了)
在创建函数时,必须严格的定义稳定性状态,否则可能导致意想不到的后果,因为PLAN CACHE以及prepared statement等原因.
函数索引必须是immutable的 .
另外稳定性选项还影响了对数据的可视特性,如
STABLEandIMMUTABLEfunctions use a snapshot established as of the start of the calling query,whereasVOLATILEfunctions obtain a fresh snapshot at the start of each query they execute.
实例:
下面来用几个时间函数来测试一下:
proname | provolatile | pronargs----------------------------------------+-------------+----------timeNow | s | 0 stabletimeofday | v | 0 volatileNow | s | 0transaction_timestamp | s | 0statement_timestamp | s | 0clock_timestamp | v | 0
其中
clock_timestamp是voatile的.Now是stable的。
halee => create table tbl_time ( id int , row_time timestamp without time zone , stat_time timestamp without time zone );CREATE TABLEINSERT 0 10000
# 情况已经很明朗了
volatile每一行都运算了,stable的只是STATEMANT开始时运算。
# 再来看看索引的比较
halee=> explain select * from tbl_time where row_time>Now();QUERY PLAN------------------------------------------------------------------------------Index Scan using idx_row_time on tbl_time (cost=0.00..4.27 rows=1 width=20)Index Cond: (row_time > Now())(2 rows)halee=> explain select * from tbl_time where row_time>clock_timestamp();QUERY PLAN--------------------------------------------------------------Seq Scan on tbl_time (cost=0.00..214.00 rows=3333 width=20)Filter: (row_time > clock_timestamp())(2 rows)
# 把clock_timestamp改成stable试试。马上就走索引了。不过这个不能乱改.
halee=> \c halee postgresYou are Now connected to database "digoal" as user "postgres".halee=# alter function clock_timestamp() strict stable;ALTER FUNCTIONhalee=# \c digoal digoalYou are Now connected to database "digoal" as user "digoal".halee=> explain select * from tbl_time where row_time>clock_timestamp();QUERY PLAN------------------------------------------------------------------------------Index Scan using idx_row_time on tbl_time (cost=0.00..4.27 rows=1 width=20)Index Cond: (row_time > clock_timestamp())(2 rows)
# 那么看看插入会不会受到影响
halee=> truncate table tbl_time;TruncATE TABLEhalee=> insert into tbl_time select generate_series(1,10000),clock_timestamp(),Now();INSERT 0 10000halee=> select count(*),count(distinct stat_time) from tbl_time;count | count | count-------+-------+-------10000 | 10000 | 1(1 row)
# 看来插入的时候还是每一个ROW运行一次。
所以三个状态都是定义层面的,不是完全的执行层面的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。