Postgre SQL
发布时间:2022-05-20 发布网站:大佬教程 code.js-code.com
大佬教程收集整理的这篇文章主要介绍了PostgreSQL 函数稳定性状态,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
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
其中
clock_timestamp是voatile的.Now是stable的。
CREATE
table
digoal
insert
into
tbl_time
SELEct
generate_serIEs
(
1
:rgb(102,
10000
),0)">clock_timestamp
(),0)">Now
();
INSERT
0
10000
digoal=> SELEct count(*),count(disTinct row_timedisTinct stat_time)from tbl_time;
count
count count
-------+-------+-------
10000 1
(1 row)
# 情况已经很明朗了
volatile每一行都运算了,stable的只是STATEMANT开始是运算。
# 再来看看索引的比较
digoal=> explain SELEct * from tbl_time where row_time>Now();
query PLAN
------------------------------------------------------------------------------
Index Scanusing IDx_row_time on tbl_time (cost=0.00..4.27 rows@H_
618_340@1
wIDth@H_
618_340@20
)
Cond:row_time Now())
(2
--------------------------------------------------------------
Seq on tbl_time @H_
618_340@214.00
3333Filter clock_timestamp)
# 很明显,volatile的函数在WHERE条件中,不走索引。而Now()即stable的函数,使用了索引。
# 把clock_timestamp改成stable试试。马上就走索引了。不过这个不能乱改.
You are Now connected to database "digoal"as user "POSTGRes".
ALTER FUNCTION
digoal=# \c digoal digoal
You are Now connected to database "digoal" as user "digoal".
query PLAN
------------------------------------------------------------------------------
Index Scan using IDx_row_time on tbl_time (cost=0.00..4.27 rows=1 wIDth=20)
(2 rows)
# 那么看看插入会不会受到影响
truncate table tbl_time;
TruncATE table
digoal insert into tbl_time generate_serIEs1:rgb(102,10000clock_timestampNow();
INSERT 010000
count
-------+-------+-------
1
)
# 看来插入的时候还是每一个ROW运行一次。
所以三个状态都是定义层面的,不是完全的执行层面的。
本图文内容来源于网友网络收集整理提供,作为学习参
考使用,版权属于原作者。
@H_472_
618@
@H_
673_613@死锁检测与解决
死锁的成因与解决方式
@H_472_
618@
@H_
673_613@数据库中的表达式
数据库中的表达式