一、函数的属性

KingbaseES 函数在定义时有三种稳定性级别:volatile、stable 和 immutable。默认情况下,创建函数的稳定性为volatile。以下是这三种函数的区别:

  • Volatile 函数可以做任何事情,包括修改数据库。在调用中,输入同样的参数可能会返回不同的结果,比如:currtid 。在一个Query中,对于每一行都会重新计算该函数。
  • Stable 函数不能修改数据库,单个Query中所有行给定同样的参数确保返回相同的结果。这种稳定级别允许优化器将多次函数调用转换为一次。在索引扫描的条件中使用这种函数是可行的,因为索引扫描只计算一次比较值(comparison value),而不是每行都计算一次。
  • Immutable 函数不能修改数据库,在任何情况下,只要输入参数相同,返回结果就相同。这种级别的函数,优化器可以提前进行计算,在查询过程中作为常量参数。比如:SELECT...WHERE x=2+2 可以简化为SELECT...WHERE x=4。
  • Deterministic  这是KingbaseES 为了与oracle 兼容而增加的一个属性,等价于 immutable 。

稳定性级别使得优化器可以判断不同函数的行为。为了得到最佳的优化结果,在创建函数时我们应该指定严格的稳定性级别。

二、不同属性对于性能的影响

以下举例说明函数的属性影响相同参数情况多次执行的效率。

1、构建函数和数据

create table test(id integer); 并插入100条完全相同的数据。

create or replace function test_volatile(id integer)
returns bigint
volatile
language sql
as
$$ select count(*) from t1 $$ ;
/ create or replace function test_stable(id integer)
returns bigint
stable
language sql
as
$$ select count(*) from t1 $$ ;
/ create or replace function test_immutable(id integer)
returns bigint
immutable
language sql
as
$$ select count(*) from t1 $$ ;
/

2、以列为参数调用函数

可以看到三个函数调用时间基本没有差别,因为,传入的参数是id 变量值(虽然实际值是相同的)。

test=# select count(*) from test where test_volatile(id)=1;
count
-------
0
(1 row) Time: 39652.495 ms (00:39.652)

test=# select count(*) from test where test_stable(id)=1;
count
-------
0
(1 row) Time: 38789.952 ms (00:38.790)

test=# select count(*) from test where test_immutable(id)=1; count
-------
0
(1 row) Time: 38591.957 ms (00:38.592)

3、函数在等式右边的情况

test=# select count(*) from test where id=test_volatile(1);
count
-------
0
(1 row) Time: 40353.777 ms (00:40.354)
test=# select count(*) from test where id=test_stable(1);
count
-------
0
(1 row) Time: 40500.253 ms (00:40.500)
test=# select count(*) from test where id=test_immutable(1);
count
-------
0
(1 row) Time: 374.300 ms

4、传入常量值

可以看到,对于常量值,stable 和 immutable 类型的函数实际只需调用一次。

test=# select count(*) from test where test_volatile(1)=1;
count
-------
0
(1 row) Time: 41647.551 ms (00:41.648)
test=# select count(*) from test where test_stable(1)=1;
count
-------
0
(1 row) Time: 399.161 ms test=# select count(*) from test where test_immutable(1)=1;
count
-------
0
(1 row) Time: 389.367 ms

5、for循环

可以看到,对于相同的输入参数, test_immutable 在同一query 只执行一次。

对于for 循环,实际结果相同。

test=# begin
test-# for i in 1..100 loop
test-# perform test_immutable(1);
test-# end loop;
test-# end;
test-# /
ANONYMOUS BLOCK
Time: 1001.184 ms (00:01.001)

6、等式右边的函数属性也会影响索引的使用

来看以下例子:

test=# create table t2(id integer,name char(999));
CREATE TABLE ^
test=# insert into t2 select generate_series(1,100),repeat('a',999);
INSERT 0 100
test=# create index ind_t2 on t2(id);
CREATE INDEX
test=#
test=# analyze t2;
ANALYZE
test=# explain analyze select count(*) from t2 where id=test_volatile(1);
QUERY PLAN
-----------------------------------------------------------------------------------------------------------
Aggregate (cost=41.25..41.26 rows=1 width=8) (actual time=38735.427..38735.428 rows=1 loops=1)
-> Seq Scan on t2 (cost=0.00..41.25 rows=1 width=0) (actual time=38735.424..38735.425 rows=0 loops=1)
Filter: (id = test_volatile(1))
Rows Removed by Filter: 100
Planning Time: 0.191 ms
Execution Time: 38735.447 ms
(6 rows) test=# explain analyze select count(*) from t2 where id=test_stable(1);
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=8.41..8.42 rows=1 width=8) (actual time=385.449..385.450 rows=1 loops=1)
-> Index Only Scan using ind_t2 on t2 (cost=0.39..8.41 rows=1 width=0) (actual time=385.446..385.446 rows=0 loops=1)
Index Cond: (id = test_stable(1))
Heap Fetches: 0
Planning Time: 398.499 ms
Execution Time: 385.487 ms
(6 rows) test=# explain analyze select count(*) from t2 where id=test_immutable(1);
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Aggregate (cost=8.16..8.17 rows=1 width=8) (actual time=0.012..0.012 rows=1 loops=1)
-> Index Only Scan using ind_t2 on t2 (cost=0.14..8.16 rows=1 width=0) (actual time=0.011..0.011 rows=0 loops=1)
Index Cond: (id = '10000000'::bigint)
Heap Fetches: 0
Planning Time: 383.902 ms
Execution Time: 0.032 ms
(6 rows) 

可以看到volatile 情况下,无法使用索引

四、oracle是怎么处理的?

SQL> create table test(id integer);

Table created.

SQL> insert into test select 1 from dba_objects where rownum<101;

100 rows created.

create or replace function test_deterministic(id integer)
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 test_volatile(id integer)
return integer
as
cnt integer;
begin
for i in 1..10 loop
select count(*) into cnt from t1 ;
end loop;
return cnt;
end ;

测试结果如下:

SQL> select * from test where id=test_volatile(1);
no rows selected
Elapsed: 00:00:50.50 SQL> select * from test where id=test_deterministic(1);
no rows selected
Elapsed: 00:00:01.04 SQL> select * from test where test_volatile(id)=1;
no rows selected
Elapsed: 00:00:50.56 --这个与KingbaseES 不同,只需调用一次
SQL> select * from test where test_deterministic(id)=1;
no rows selected
Elapsed: 00:00:01.02 --这个与KingbaseES 不同,只需调用一次
SQL> select * from test where test_volatile(1)=1;
no rows selected
Elapsed: 00:00:00.51 SQL> select * from test where test_deterministic(1)=1;
no rows selected
Elapsed: 00:00:00.52

KingbaseES 与Oracle 函数稳定性对于性能影响差异比较的更多相关文章

  1. KingbaseES 函数稳定性与SQL性能

    背景:客户现场的一次艰苦的调优过程(https://www.cnblogs.com/kingbase/p/16015834.html),让我觉得非常有必要让数据库用户了解函数的不同稳定性属性,及其对于 ...

  2. 痞子衡嵌入式:简析i.MXRT1170 Cortex-M7 FlexRAM ECC功能特点、开启步骤、性能影响

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M7内核的FlexRAM ECC功能. ECC是"Error Correcting ...

  3. 痞子衡嵌入式:简析i.MXRT1170 Cortex-M4 L-MEM ECC功能特点、开启步骤、性能影响

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M4内核的L-MEM ECC功能. 本篇是 <简析i.MXRT1170 Cortex-M ...

  4. 盘点 Oracle 11g 中新特性带来的10大性能影响

    Oracle的任何一个新版本,总是会带来大量引人瞩目的新特性,但是往往在这些新特性引入之初,首先引起的是一些麻烦,因为对于新技术的不了解.因为对于旧环境的不适应,从Oracle产品到技术服务运维,总是 ...

  5. 如何让Oracle数据库保持优良性能的方法

    OracleDatabase,又名OracleRDBMS,或简称Oracle.是甲骨文公司的一款关系数据库管理系统.它是在数据库领域一直处于领先地位的产品.可以说Oracle数据库系统是目前世界上流行 ...

  6. 万级K8s集群背后etcd稳定性及性能优化实践

    背景与挑战 随着腾讯自研上云及公有云用户的迅速增长,一方面,腾讯云容器服务TKE服务数量和核数大幅增长, 另一方面我们提供的容器服务类型(TKE托管及独立集群.EKS弹性集群.edge边缘计算集群.m ...

  7. 万级K8s集群背后 etcd 稳定性及性能优化实践

    1背景与挑战随着腾讯自研上云及公有云用户的迅速增长,一方面,腾讯云容器服务TKE服务数量和核数大幅增长, 另一方面我们提供的容器服务类型(TKE托管及独立集群.EKS弹性集群.edge边缘计算集群.m ...

  8. ToList<>()所带来的性能影响

    ToList<>()所带来的性能影响  前几天优化师弟写的代码,有一个地方给我留下很深刻的印象,就是我发现他总是将PLINQ的结果ToList<>(),然后再返回给主程序,对于 ...

  9. oracle函数操作

    感于总有些网友提出一些非常基础的问题,比如有没有实现某某功能的函数啊,某某函数是做什么用的啊,格式是什么等等,同时也感受到自己对oracle函数认识的不足,于是集中月余时间专注于oracle函数,小有 ...

随机推荐

  1. python 基础知识-day6(内置函数)

    1.sorted():用于字典的排序 dict1={"name":"cch","age":"3","sex&q ...

  2. exe4j下载和使用

    https://blog.csdn.net/weixin_44678104/article/details/101015065

  3. 数据库 OLAP、OLTP是什么?相同和不同?适用场景

    一.OLTP和OLAP是什么,二者比较 人类世界遵从基本的物理规律,数据世界里,关于数据的操作处理,也大体分为OLTP和OLAP两类. OLTP on-line transaction process ...

  4. 一张图进阶 RocketMQ - 消息发送

    前 言 三此君看了好几本书,看了很多遍源码整理的 一张图进阶 RocketMQ 图片链接,关于 RocketMQ 你只需要记住这张图!觉得不错的话,记得点赞关注哦. [重要]视频在 B 站同步更新,欢 ...

  5. 常用Linux命令整理

    常见系统命令 export 查看或修改环境变量 # 例:临时修改命令提示符为字符串$ export PS1=$ # 例:临时修改命令提示符显示系统时间 时间使用\t 表示 export PS1=&qu ...

  6. APISpace 日出日落API接口 免费好用

    日出是每个早晨太阳的一半从地平线探出头的时刻,也指太阳穿过地平线的整个过程及其伴随的大气效应.日落是指由于地球自转导致太阳每天从地平线消失的时刻.从赤道上看,春分和秋分时,太阳从正西方落下.从中纬度地 ...

  7. C++ 加速(卡常)技巧【超级 快读、快写】

    C++ \texttt{C++} C++ 加速技巧 快读快写 快读 inline int read() { int x = 0, w = 0; char ch = 0; while (!isdigit ...

  8. ROS机械臂 Movelt 学习笔记2 | Move Group 接口 C++

    Movelt为使用者提供了一个最通用且简单的接口 MoveGroupInterface 类,这个接口提供了很多控制机器人的常用基本操作,如: 设置机械臂的位姿 进行运动规划 移动机器人本体 将物品添加 ...

  9. CF1702B Polycarp Writes a Srting from Memory 题解

    给定一个字符串,每天可以记忆三个字符,求书写出整个字符串的天数. 每次确定要记忆的三个字母,并向后寻找,若有非三个字母其中一个,则重新开启一天记忆三个字母. #include<cstdio> ...

  10. 背包问题学习笔记 / Dynamic Programming(updating)

    01背包问题     朴素版:(二维数组) 状态表示: dp[i][j]:从前i个物品中选择(每个物品只能选0或1个)且总体积不超过j的集合的最大价值,则dp[n][m]就是最终答案(n:物品数量,m ...