immutable 与 stable 函数的差异
- Stable 函数不能修改数据库,单个Query中所有行给定同样的参数确保返回相同的结果。这种稳定级别允许优化器将多次函数调用转换为一次。在索引扫描的条件中使用这种函数是可行的,因为索引扫描只计算一次比较值(comparison value),而不是每行都计算一次。
- Immutable 函数不能修改数据库,在任何情况下,只要输入参数相同,返回结果就相同。这种级别的函数,优化器可以提前进行计算,在查询过程中作为常量参数。比如:SELECT...WHERE x=2+2 可以简化为SELECT...WHERE x=4。
以下以例子说明二者的差异。
一、KingbaseES
1、准备数据
create table t1(id1 integer,id2 integer);
insert into t1 select generate_series(1,10000000),generate_series(1,10000000); test=# \timing on
Timing is on.
test=# select count(*) from t1;
count
----------
10000000
(1 row) Time: 681.445 ms
2、创建immutable 和 stable 函数
create or replace function f001()
returns bigint
immutable
language sql
as
$$ select count(*) from t1 $$ ; create or replace function f002()
returns bigint
stable
language sql
as
$$ select count(*) from t1 $$ ;
3、单独explain 函数
可以看到对于 immutable 函数,在 explain 时,实际会去执行的;而stable 函数,explain 时则不会实际执行。
test=# explain select f001();
QUERY PLAN
------------------------------------------
Result (cost=0.00..0.01 rows=1 width=8)
(1 row) Time: 450.572 ms
test=# explain select f002();
QUERY PLAN
------------------------------------------
Result (cost=0.00..0.26 rows=1 width=8)
(1 row) Time: 0.641 ms test=# select f001();
f001
----------
10000000
(1 row) Time: 448.720 ms
test=# select f002();
f002
----------
10000000
(1 row) Time: 426.745 ms
4、例子一
可以看到 immutable 函数执行时间主要花在planning上,也就是在制定执行计划前,就已经取得函数的值;而 stable 函数,则在语句解析和执行时,都要执行函数,而且,针对语句的访问的每个tuple,都要执行一次函数调用。
test=# explain analyze select * from (select * from t1 limit 10) a where a.id1=f001();
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Subquery Scan on a (cost=0.00..0.27 rows=1 width=8) (actual time=0.012..0.013 rows=0 loops=1)
Filter: (a.id1 = '10000000'::bigint)
Rows Removed by Filter: 10
-> Limit (cost=0.00..0.15 rows=10 width=8) (actual time=0.009..0.010 rows=10 loops=1)
-> Seq Scan on t1 (cost=0.00..148609.21 rows=10007621 width=8) (actual time=0.008..0.009 rows=10 loops=1)
Planning Time: 413.963 ms
Execution Time: 0.026 ms
(7 rows) test=# explain analyze select * from (select * from t1 limit 10) a where a.id1=f002();
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Subquery Scan on a (cost=0.00..2.77 rows=1 width=8) (actual time=3691.788..3691.788 rows=0 loops=1)
Filter: (a.id1 = f002())
Rows Removed by Filter: 10
-> Limit (cost=0.00..0.15 rows=10 width=8) (actual time=0.012..0.028 rows=10 loops=1)
-> Seq Scan on t1 (cost=0.00..148609.21 rows=10007621 width=8) (actual time=0.011..0.021 rows=10 loops=1)
Planning Time: 364.233 ms
Execution Time: 3691.807 ms
(7 rows) Time: 4056.907 ms (00:04.057) test=# explain analyze select * from (select * from t1 where 1=2) a where a.id1=f002();
QUERY PLAN
------------------------------------------------------------------------------------------
Result (cost=0.00..2675533.51 rows=1 width=8) (actual time=0.001..0.001 rows=0 loops=1)
One-Time Filter: false
-> Seq Scan on t1 (cost=0.00..2675533.51 rows=1 width=8) (never executed)
Filter: (id1 = f002())
Planning Time: 490.720 ms
Execution Time: 0.017 ms
(6 rows) test=# explain analyze select * from (select * from t1 limit 1) a where a.id1=f002();
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Subquery Scan on a (cost=0.00..0.28 rows=1 width=8) (actual time=390.833..390.834 rows=0 loops=1)
Filter: (a.id1 = f002())
Rows Removed by Filter: 1
-> Limit (cost=0.00..0.01 rows=1 width=8) (actual time=0.024..0.053 rows=1 loops=1)
-> Seq Scan on t1 (cost=0.00..148609.21 rows=10007621 width=8) (actual time=0.023..0.023 rows=1 loops=1)
Planning Time: 426.693 ms
Execution Time: 390.852 ms
(7 rows)
5、例子二
sysdate 函数 为 stable 时:sysdate 函数在同一事务内多次执行返回的结果都相同,跨事务则每次结果不同。
test=# begin
test-# for i in 1..5 loop
test-# raise notice '%', sysdate();
test-# perform sys_sleep(1);
test-# commit;
test-# end loop;
test-# end;
test-# /
NOTICE: 2022-06-29 19:53:18
NOTICE: 2022-06-29 19:53:19
NOTICE: 2022-06-29 19:53:20
NOTICE: 2022-06-29 19:53:21
NOTICE: 2022-06-29 19:53:22
ANONYMOUS BLOCK
Time: 5011.031 ms (00:05.011) test=# begin
test-# for i in 1..5 loop
test-# raise notice '%', sysdate();
test-# perform sys_sleep(1);
test-# end loop;
test-# end;
test-# /
NOTICE: 2022-06-29 19:54:14
NOTICE: 2022-06-29 19:54:14
NOTICE: 2022-06-29 19:54:14
NOTICE: 2022-06-29 19:54:14
NOTICE: 2022-06-29 19:54:14
ANONYMOUS BLOCK
Time: 5005.724 ms (00:05.006)
sysdate 函数为 immutable 时:不管是否跨事务,sysdate 函数结果都相同。
test=# alter function sysdate immutable;
ALTER FUNCTION
Time: 6.276 ms
test=# begin
test-# for i in 1..5 loop
test-# raise notice '%', sysdate();
test-# perform sys_sleep(1);
test-# commit;
test-# end loop;
test-# end;
test-# /
NOTICE: 2022-06-29 19:54:58
NOTICE: 2022-06-29 19:54:58
NOTICE: 2022-06-29 19:54:58
NOTICE: 2022-06-29 19:54:58
NOTICE: 2022-06-29 19:54:58
ANONYMOUS BLOCK
Time: 5007.899 ms (00:05.008)
test=# begin
test-# for i in 1..5 loop
test-# raise notice '%', sysdate();
test-# perform sys_sleep(1);
test-# end loop;
test-# end;
test-# /
NOTICE: 2022-06-29 19:55:11
NOTICE: 2022-06-29 19:55:11
NOTICE: 2022-06-29 19:55:11
NOTICE: 2022-06-29 19:55:11
NOTICE: 2022-06-29 19:55:11
ANONYMOUS BLOCK
Time: 5007.694 ms (00:05.008)
二、Oracle
1、创建函数
create or replace function f001
return integer
deterministic
as
cnt integer;
begin
for i in 1..10 loop
select count(*) into cnt from t1 ;
end loop;
return cnt;
end ; create or replace function f002
return integer
as
cnt integer;
begin
for i in 1..10 loop
select count(*) into cnt from t1 ;
end loop;
return cnt;
end ;
2、单独explain 函数
可以看到两个函数都不会执行,不管是 deterministic,还是 volatile
SQL> explain plan for select f001() from dual; Explained. Elapsed: 00:00:00.00
SQL> explain plan for select f002() from dual; Explained. Elapsed: 00:00:00.00
3、实际执行
deterministic 只需执行一次,但是在SQL执行时才执行函数调用,而非explain时;volatile 解析时,不需要调用函数,而针对每个tuple 都必须要调用一次,如果没有记录,则无需调用。
SQL> select * from (select * from t1 where rownum<11) where id1=f001(); no rows selected Elapsed: 00:00:00.48 SQL> select * from (select * from t1 where rownum<11) where id1=f002(); no rows selected Elapsed: 00:00:05.01 SQL> select * from (select * from t1 where 1=2) where id1=f002(); no rows selected Elapsed: 00:00:00.00
immutable 与 stable 函数的差异的更多相关文章
- PHP 日期计算函数【差异天数】
function count_days($a,$b){ $a_dt=getdate($a); $b_dt=getdate($b); $a_new=mktime(12,0,0,$a_dt['mon'], ...
- 十八般武艺玩转GaussDB(DWS)性能调优:SQL改写
摘要:本文将系统介绍在GaussDB(DWS)系统中影响性能的坏味道SQL及SQL模式,帮助大家能够从原理层面尽快识别这些坏味道SQL,在调优过程中及时发现问题,进行整改. 数据库的应用中,充斥着坏味 ...
- Oracle 与 PostgreSQL 函数行为的差异引发性能差异
对于Oracle,对于数据修改的操作通过存储过程处理,而对于函数一般不进行数据修改操作.同时,函数可以通过 Select 进行调用,而存储过程则不行. 一.对于volatile 函数的行为 1.Ora ...
- KingbaseES 与Oracle 函数稳定性对于性能影响差异比较
一.函数的属性 KingbaseES 函数在定义时有三种稳定性级别:volatile.stable 和 immutable.默认情况下,创建函数的稳定性为volatile.以下是这三种函数的区别: V ...
- PG 函数的易变性(Function Volatility Categories)
此概念的接触是在做分区表的时候碰到的,分区表按时间字段分区,在查询时当where条件中时间为now()或者current_time()等时是无法查询的,即使进行格式转换也不行,只有是时间格式如‘201 ...
- CREATE FUNCTION - 定义一个新函数
SYNOPSIS CREATE [ OR REPLACE ] FUNCTION name ( [ argtype [, ...] ] ) RETURNS rettype { LANGUAGE lang ...
- KingbaseES 函数稳定性与SQL性能
背景:客户现场的一次艰苦的调优过程(https://www.cnblogs.com/kingbase/p/16015834.html),让我觉得非常有必要让数据库用户了解函数的不同稳定性属性,及其对于 ...
- 《zw版·delphi与halcon系列原创教程》zw版_THOperatorSetX控件函数列表 v11中文增强版
<zw版·delphi与halcon系列原创教程>zw版_THOperatorSetX控件函数列表v11中文增强版 Halcon虽然庞大,光HALCONXLib_TLB.pas文件,源码就 ...
- 《zw版·delphi与halcon系列原创教程》zw版_THImagex控件函数列表
<zw版·delphi与halcon系列原创教程>zw版_THImagex控件函数列表 Halcon虽然庞大,光HALCONXLib_TLB.pas文件,源码就要7w多行,但核心控件就是两 ...
随机推荐
- SAP Web Dynpro-调试应用程序
您可以使用ABAP工作台中的各种工具来调试源代码. 您可以使用调试器测试Web Dynpro应用程序的所有源代码. 步骤1-要启动调试器,您必须在ABAP工作台中选择一个新的调试器. 步骤2-转到实用 ...
- UiPath参数介绍和使用
一.参数介绍 用于将数据从一个项目传递到另一个项目.在全局意义上,它们类似于变量,因为它们动态地存储数据并传递给它.变量在活动之间传递数据,而参数在自动化之间传递数据.因此,它们使你能够一次又一次地重 ...
- 周报?谁还写周报啊?不都用Python小工具: 发个周报邮件给老板就行还写周报啊?不都用Python小工具: 发个周报邮件给老板就行
缘起: 新跳槽到一家公司, 没想到第一个挑战居然是每周都要发周报. 告诉老板这周都干了些什么和下周准备干什么. 我记性不好, 常常忘事儿.所以很多时候周报都会忘记发送. 于是, 就决定写一个小工具好了 ...
- 腾讯云原生数据库TDSQL-C入选信通院《云原生产品目录》
近日,中国信通院.云计算开源产业联盟正式对外发布<云原生产品目录>,腾讯云原生数据库TDSQL-C凭借其超强性能.极致效率的弹性伸缩和完善的产品化解决方案体系,成功入围目录. 全球数字经济 ...
- CMU15445 (Fall 2019) 之 Project#2 - Hash Table 详解
前言 该实验要求实现一个基于线性探测法的哈希表,但是与直接放在内存中的哈希表不同的是,该实验假设哈希表非常大,无法整个放入内存中,因此需要将哈希表进行分割,将多个键值对放在一个 Page 中,然后搭配 ...
- 聊聊 C++ 大一统的初始化运算符 {}
一:背景 最近发现 C++ 中的类型初始化操作,没有 {} 运算符搞不定的,蛮有意思,今天我们就来逐一列一下各自的用法以及汇编展现,本来想分为 值类型 和 引用类型 两大块,但发现在 C++ 中没这种 ...
- Java的基础语法01
一. 注释,标识符,关键字 书写注释是一种习惯的养成,当我们一段代码完成后,长时间没有回顾,便会产生遗忘,所以注释是给我们写代码的人看的.1.注释 //单行注释 /*多行注释*/ /**文档注释也叫文 ...
- C# 基础知识-反射
一.反射 1>反射的命名空间是System.Reflection 2>是.Net框架提供的帮助类库,读取并使用matedata 二.反射基本用法 举例如下 1>Assembly as ...
- C#爬虫之通过Selenium获取浏览器请求响应结果
前言 在进行某些爬虫任务的时候,我们经常会遇到仅用Http协议难以攻破的情况,比如协议中带有加密参数,破解需要花费大量时间,那这时候就会用Selenium去模拟浏览器进行页面上的元素抓取 大多数情况下 ...
- 技术分享 | MySQL中MGR中SECONDARY节点磁盘满,导致mysqld进程被OOM Killed
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 在MGR测试中,人为制造磁盘满问题后,节点被oom killed 问题描述 在对 ...