Postgresql函数稳定性学习

Postgresql函数稳定性学习,第1张

概述PostgreSQL 函数在定义的时候有三个稳定性状态可选: IMMUTABLE | STABLE | VOLATILE 分别代表,非常稳定,稳定,不稳定。 不稳定,函数可以修改数据库的数据,输入同样的参数可以返回不同的结果,同一个QUERY中,如果需要返回该函数的结果,那么每一行都会运算一遍这个函数(后面会有例子)。 稳定,函数不可以修改数据库的数据,同一个QUERY中,如果需要返回该函数的结果 Postgresql 函数在定义的时候有三个稳定性状态可选: IMMUtable | Stable | VolATILE 分别代表,非常稳定,稳定,不稳定。
不稳定,函数可以修改数据库的数据,输入同样的参数可以返回不同的结果,同一个query中,如果需要返回该函数的结果,那么每一行都会运算一遍这个函数(后面会有例子)。 稳定,函数不可以修改数据库的数据,同一个query中,如果需要返回该函数的结果,那么将合并多次运算为一次这个函数(后面会有例子)。另外,只有stable和immutable的函数才可以被执行计划选择作为索引的比较条件。(因为索引比较时,被比较的值只运算一次.这个就需要stable和immutable了) 非常稳定,函数不可以修改数据库的数据,并且在任何情况下调用,只要输入参数一致,返回结果都一致。
在创建函数时,必须严格的定义稳定性状态,否则可能导致意想不到的后果,因为PLAN CACHE以及prepared statement等原因. 函数索引必须是immutable的 .
注意稳定和非常稳定的函数中只能出现SELECT语句。
但是SELECT语句中可以调用不稳定函数,因此这些稳定性选项都不是强限制。 另外稳定性选项还影响了对数据的可视特性,如 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 stable                          timeofday               | v      |    0 volatile                          Now                  | s      |    0                          transaction_timestamp         | s      |    0                          statement_timestamp          | s      |    0                          clock_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       table                   digoal      =>       insert       into       tbl_time       select       generate_serIEs      (      1      ,      10000      ),      clock_timestamp      (),      Now      ();                   INSERT       0             10000                                            halee=> select count(*),count(distinct row_time),count(distinct stat_time) from tbl_time;                   count | count | count                   -------+-------+-------                   10000 | 10000 |   1                   (1 row)           

# 情况已经很明朗了 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)      
# 很明显,volatile的函数在WHERE条件中,不走索引。而Now()即stable的函数,使用了索引。
# 把clock_timestamp改成stable试试。马上就走索引了。不过这个不能乱改.
              halee=> \c halee postgres                    You are Now connected to database "digoal" as user "postgres".                    halee=# alter function clock_timestamp() strict stable;                    ALTER FUNCTION                    halee=# \c digoal digoal                    You 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 table                          halee=> insert into tbl_time select generate_serIEs(1,10000),clock_timestamp(),Now();                          INSERT 0 10000                          halee=> select count(*),count(distinct stat_time) from tbl_time;                          count | count | count                          -------+-------+-------                          10000 | 10000 |   1                          (1 row)        
# 看来插入的时候还是每一个ROW运行一次。
所以三个状态都是定义层面的,不是完全的执行层面的。 总结

以上是内存溢出为你收集整理的Postgresql函数稳定性学习全部内容,希望文章能够帮你解决Postgresql函数稳定性学习所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1175528.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存