PostgreSQL 函数稳定性状态

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: PostgreSQL 函数在定义的时候有三个稳定性状态可选:IMMUTABLE | STABLE | VOLATILE分别代表,非常稳定,稳定,不稳定。
PostgreSQL 函数在定义的时候有三个稳定性状态可选:
IMMUTABLE | STABLE | VOLATILE
分别代表,非常稳定,稳定,不稳定。

不稳定,函数可以修改数据库的数据,输入同样的参数可以返回不同的结果,同一个QUERY中,如果需要返回该函数的结果,那么每一行都会运算一遍这个函数(后面会有例子)。
稳定,函数不可以修改数据库的数据,同一个QUERY中,如果需要返回该函数的结果,那么将合并多次运算为一次这个函数(后面会有例子)。另外,只有stable和immutable的函数才可以被执行计划选择作为索引的比较条件。(因为索引比较时,被比较的值只运算一次.这个就需要stable和immutable了)
非常稳定,函数不可以修改数据库的数据,并且在任何情况下调用,只要输入参数一致,返回结果都一致。

在创建函数时,必须严格的定义稳定性状态,否则可能导致意想不到的后果,因为PLAN CACHE以及prepared statement等原因.
函数索引必须是immutable的 . 

注意稳定和非常稳定的函数中只能出现SELECT语句。但是SELECT语句中可以调用不稳定函数,因此这些稳定性选项都不是强限制。
另外稳定性选项还影响了对数据的可视特性,如  STABLE and IMMUTABLE functions use a snapshot established as of the start of the calling query, whereas VOLATILE functions obtain a fresh snapshot at the start of each query they execute.

实例:
下面来用几个时间函数来测试一下:
 
   

                proname                 | provolatile | pronargs 
----------------------------------------+-------------+----------
 timenow                                | s           |        0
 timeofday                              | v           |        0
 now                                    | s           |        0
 transaction_timestamp                  | s           |        0
 statement_timestamp                    | s           |        0
 clock_timestamp                        | v           |        0


其中
clock_timestamp是voatile的.now是stable的。

 
  

digoal => 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
digoal=> select count(*),count(distinct row_time),count(distinct stat_time) from tbl_time;
 count | count | count 
-------+-------+-------
 10000 | 10000 |     1
(1 row)


# 情况已经很明朗了
volatile每一行都运算了,stable的只是STATEMANT开始是运算。
# 再来看看索引的比较
 
  

digoal=> 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)

digoal=> 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试试。马上就走索引了。不过这个不能乱改.
 
  

digoal=> \c digoal postgres
You are now connected to database "digoal" as user "postgres".
digoal=# alter function clock_timestamp() strict stable;
ALTER FUNCTION
digoal=# \c digoal digoal
You are now connected to database "digoal" as user "digoal".
digoal=> 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)


# 那么看看插入会不会受到影响
 
   

digoal=> truncate table tbl_time;
TRUNCATE TABLE
digoal=> insert into tbl_time select generate_series(1,10000),clock_timestamp(),now();
INSERT 0 10000
digoal=> select count(*),count(distinct row_time),count(distinct stat_time) from tbl_time;
 count | count | count 
-------+-------+-------
 10000 | 10000 |     1
(1 row)

# 看来插入的时候还是每一个ROW运行一次。

所以三个状态都是定义层面的,不是完全的执行层面的。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
25天前
|
JSON 关系型数据库 MySQL
Mysql(5)—函数
MySQL提供了许多内置的函数以帮助用户进行数据操作和分析。这些函数可以分为几类,包括聚合函数、字符串函数、数值函数、日期和时间函数、控制流函数等。
68 1
Mysql(5)—函数
|
2月前
|
关系型数据库 Serverless 定位技术
PostgreSQL GIS函数判断两条线有交点的函数是什么?
PostgreSQL GIS函数判断两条线有交点的函数是什么?
210 60
|
6天前
|
关系型数据库 MySQL Serverless
MySQL函数
最常用的MySQL函数,包括聚合函数,字符串函数,日期时间函数,控制流函数等
|
9天前
|
SQL NoSQL 关系型数据库
|
1月前
|
存储 SQL 关系型数据库
MySQL 存储函数及调用
MySQL 存储函数及调用
34 3
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 满足条件函数中使用查询最大值函数
MySQL 满足条件函数中使用查询最大值函数
98 1
|
2月前
|
存储 SQL 关系型数据库
MySQL基础:函数
本文介绍了MySQL中几种常用的内建函数,包括字符串函数、数值函数、日期函数和流程函数。字符串函数如`CONCAT()`用于拼接字符串,`TRIM()`用于去除字符串两端的空格,`MOD()`求余数,`RAND()`生成随机数,`ROUND()`四舍五入。日期函数如`CURDATE()`返回当前日期,`NOW()`返回当前日期和时间,`DATE_ADD()`添加时间间隔,`DATEDIFF()`计算日期差。流程函数如`IF()`和`CASE WHEN THEN ELSE END`用于条件判断。聚合函数如`COUNT()`统计行数,`SUM()`求和,`AVG()`求平均值
28 8
MySQL基础:函数
|
20天前
|
关系型数据库 MySQL 数据库
mysql中tonumber函数使用要注意什么
在处理这类转换操作时,考虑周全,利用提供的高性能云服务器资源,可以进一步提升数据库处理效率,确保数据操作的稳定性和安全性,尤其是在处理大量数据转换和运算密集型应用时。
66 0
|
24天前
|
关系型数据库 MySQL 数据处理
企业级应用 mysql 日期函数变量,干货已整理
本文详细介绍了如何在MySQL8.0中使用DATE_FORMAT函数进行日期格式的转换,包括当日、昨日及不同时间段的数据获取,并提供了实际的ETL应用场景和注意事项,有助于提升数据处理的灵活性和一致性。
37 0
|
2月前
|
JSON 关系型数据库 MySQL
MySQL 8.0常用函数汇总与应用实例
这些函数只是MySQL 8.0提供的众多强大功能的一部分。通过结合使用这些函数,你可以有效地处理各种数据,优化数据库查询,并提高应用程序的性能和效率。
52 3