函数的稳定性表现差异 IMMUTABLE | STABLE | VOLATILE

2025博客之星年度评选已开启 10w+人浏览 1.6k人参与

函数的稳定性

函数稳定性参数的三种状态

  • IMMUTABLE:函数在plan时执行且只执行一次。在 select 后面调用序列只会生成多个相同的值;在 where 后面调用序列只会生成多个相同的值
  • STABLE:函数在execute时执行。在 select 后面调用序列会生成多个不同的值;在 where 后面调用序列只会生成多个相同的值
  • VOLATILE:函数在execute时执行。在 select 后面调用序列会生成多个不同的值;在 where 后面调用序列会生成多个不同的值。默认值
函数稳定性参数执行时刻SELECT后调用序列WHERE后调用
IMMUTABLEPLAN生成多个相同的值生成多个相同的值
STABLEEXECUTE生成多个不同的值生成多个相同的值
VOLATILEEXECUTE生成多个不同的值生成多个不同的值默认值

稳定性:immutable > stable > volatile
⚠️注意:序列无法回滚

下面分别演示在事务里、在同一条SQL里和在where后调用这3种状态的不同表现

构造测试环境

-- 查看nextval的函数定义
10:10:42 pg14@testdb=# \sf nextval
CREATE OR REPLACE FUNCTION pg_catalog.nextval(regclass)
 RETURNS bigint
 LANGUAGE internal
 STRICT
AS $function$nextval_oid$function$
-- 创建自定义测试函数test_nextval
CREATE OR REPLACE FUNCTION test_nextval(regclass)
 RETURNS bigint
 LANGUAGE internal
 STRICT
AS $function$nextval_oid$function$;
-- 创建测试序列
create sequence test_sequence;

image.png

在事务里调用

行为一致,没有差别

alter function test_nextval(regclass) immutable;

-- 事务里调用
begin;
select test_nextval('test_sequence'),test_nextval('test_sequence');
rollback;

alter function test_nextval(regclass) stable;

alter function test_nextval(regclass) volatile;

image.png
image.png

同一条SQL里调用

指定 immutable 的函数执行计划的计划器在解析sql并执行的时不管有多少条记录,只会执行一次

alter function test_nextval(regclass) immutable;

-- 同一条SQL里调用
select test_nextval('test_sequence'::regclass) from generate_series(1,3);

alter function test_nextval(regclass) stable;

alter function test_nextval(regclass) volatile;

image.png

WHERE后调用

放在 WHERE 后调用,指定 immutablestable 的函数只执行一次,默认的 volatile 会执行多次

select currval('test_sequence');

alter function test_nextval(regclass) immutable;

-- where后调用
select * from (select generate_series(1,5)) as temp where test_nextval('test_sequence')=17;

alter function test_nextval(regclass) stable;

alter function test_nextval(regclass) volatile;

image.png
image.png

在 IT 领域,尤其是数据库系统如 PostgreSQL 中,volatileimmutablestable 用于描述函数稳定性级别,它们影响着优化器的行为。 ### Volatile(易变) 含义:表示函数可能在任何时候改变结果,是函数稳定性的默认级别。 特点:函数的返回值可能随时间、外部环境变化而变化,每次调用可能得到不同结果。 应用:常用于那些依赖外部状态、有副作用或返回值不固定的函数。例如,获取当前时间的函数,由于时间不断变化,每次调用都会返回不同结果,就属于 volatile 函数。在 PostgreSQL 中,插入、更新、删除等会改变数据库状态的操作函数通常也是 volatile 的。 ### Immutable(不可变) 含义:对于相同输入总是返回相同结果,是一种纯函数函数不能修改数据库,且不做数据库查找或使用未在参数列表中直接出现的信息。 特点:只要输入参数相同,无论何时何地调用该函数,返回值都不会改变。给定全常量参数调用该函数时,可立刻用函数值替换。 应用:适用于数学计算、字符串处理、加密解密等确定性操作的函数。例如,计算两个数之和的函数,只要输入的两个数确定,结果就固定不变,这类函数可定义为 immutable 函数,有助于优化器在查询优化时进行常量折叠等操作,提高查询性能。 ### Stable(稳定) 含义:在单个语句中对于相同输入返回相同结果。 特点:在同一条 SQL 语句的执行过程中,相同输入的函数调用返回值保持不变,但在不同语句中,即使输入相同,返回值可能不同。 应用:常用于那些在一次查询中结果稳定,但在不同查询之间可能变化的函数。例如,统计某个表在当前事务中的记录数,在同一条查询语句里多次调用该统计函数,结果是相同的,但如果在不同事务或不同时间执行查询,表的记录数可能已改变,函数返回值就会不同。 ```sql -- 示例:定义不同稳定性级别的函数 -- Immutable 函数:计算两个整数之和 CREATE OR REPLACE FUNCTION add_numbers(a integer, b integer) RETURNS integer AS $$ BEGIN RETURN a + b; END; $$ LANGUAGE plpgsql IMMUTABLE; -- Stable 函数:统计某个表的记录数 CREATE OR REPLACE FUNCTION count_table_rows(table_name regclass) RETURNS bigint AS $$ DECLARE row_count bigint; BEGIN EXECUTE 'SELECT count(*) FROM ' || quote_ident(table_name::text) INTO row_count; RETURN row_count; END; $$ LANGUAGE plpgsql STABLE; -- Volatile 函数:获取当前时间 CREATE OR REPLACE FUNCTION get_current_time() RETURNS timestamp AS $$ BEGIN RETURN current_timestamp; END; $$ LANGUAGE plpgsql VOLATILE; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值