金仓数据库KingbaseES 函数稳定性与子查询提升

目录

一、函数的三种稳定态

二、Volatile 函数影响子查询提升

1、构建例子

2、volatile 函数影响子查询提升

3、immutable 函数与执行计划

三、结论


一、函数的三种稳定态

函数的稳定性状态,简单地说就是相同的输入参数情况下,函数返回值是否相同。

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

  • 如果本应该是 volatile ,而设置成 immutable,会导致结果错误。如:currtid 函数,不同时刻执行的结果可能是不同的,必须是volatile 。
  • 如果本应该是 immutable,而设置成 volatile , 就会导致性能问题。如:trunc 函数,不同时刻执行结果应该是相同的,只需执行一次即可。

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

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

KingbaseES 为了兼容Oracle,增加了 Deterministic稳定态,等价于 immutable 。

二、Volatile 函数影响子查询提升

1、构建例子

create table tab1(id1 integer,name1 varchar(9),addr1 text);
create table tab2(id2 integer,name2 varchar(9),addr2 text);
insert into tab1 select generate_series(1,1000000),generate_series(1,1000000),'abc';
insert into tab2 select generate_series(1,1000000),generate_series(1,1000000),'abc';
create index ind_tab1 on tab1(id1);
create index ind_tab2 on tab2(id2)

2、volatile 函数影响子查询提升

对于 tab2 表的访问无法使用索引。

test=# \df+ replace                                                                                                             
                                                                                      List of functions
 Schema |  Name   | Result data type  | Argument data types | Type | Volatility | Parallel | Owner  | Security | Access privileges | Language |           Source code           | Description
--------+---------+-------------------+---------------------+------+------------+----------+--------+----------+-------------------+----------+---------------------------------+-------------
 sys    | replace | character varying | text, text, text    | func | volatile   | safe     | system | invoker  |                   | c        | ora_replace_text                |
test=# explain select id1,name1 from tab1 a ,(select id2,replace(id2,'b','B') name2 from tab2 ) b where a.id1=b.id2 and name1='123';
                             QUERY PLAN                             
---------------------------------------------------------------------
 Hash Join  (cost=17935.01..52120.02 rows=1 width=10)
   Hash Cond: (tab2.id2 = a.id1)
   ->  Seq Scan on tab2  (cost=0.00..20435.00 rows=1000000 width=36)
   ->  Hash  (cost=17935.00..17935.00 rows=1 width=10)
         ->  Seq Scan on tab1 a  (cost=0.00..17935.00 rows=1 width=10)
               Filter: ((name1)::text = '123'::text)
(6 rows)

不使用子查询情况下的,可以使用索引:

test=# explain select  id1,name1,id2,replace(id2,'b','B') name2 from tab1 a,tab2 b where a.id1=b.id2 and name1='123';
                                  QUERY PLAN                                 
------------------------------------------------------------------------------
 Nested Loop  (cost=0.42..17943.46 rows=1 width=46)
   ->  Seq Scan on tab1 a  (cost=0.00..17935.00 rows=1 width=10)
         Filter: ((name1)::text = '123'::text)
   ->  Index Only Scan using ind_tab2 on tab2 b  (cost=0.42..8.44 rows=1 width=4)
         Index Cond: (id2 = a.id1)
(5 rows)

3、immutable 函数与执行计划

改成immutable 函数后,子查询可以提升,从而能够使用索引。

test=# \df+ replace
                                                                                      List of functions
 Schema |  Name   | Result data type  | Argument data types | Type | Volatility | Parallel | Owner  | Security | Access privileges | Language |           Source code           | Description
--------+---------+-------------------+---------------------+------+------------+----------+--------+----------+-------------------+----------+---------------------------------+-------------
 sys    | replace | character varying | text, text, text    | func | immutable  | safe     | system | invoker  |                   | c        | ora_replace_text                |
test=# explain select id1,name1 from tab1 a ,(select id2,replace(id2,'b','B') name2 from tab2 ) b where a.id1=b.id2 and name1='123';
                                 QUERY PLAN                                
----------------------------------------------------------------------------
 Nested Loop  (cost=0.42..17943.45 rows=1 width=10)
   ->  Seq Scan on tab1 a  (cost=0.00..17935.00 rows=1 width=10)
         Filter: ((name1)::text = '123'::text)
   ->  Index Only Scan using ind_tab2 on tab2  (cost=0.42..8.44 rows=1 width=4)
         Index Cond: (id2 = a.id1)
(5 rows)

三、结论

函数的稳定性特性不是KingbaseES独有的,Oracle 也有同样的机制(默认volatile , 可以加 deterministic),不同的稳定态会影响性能及数据的准确性。

用户在创建函数时,必须对了解自己所创建的函数应归属的属性,错误的属性设置可能导致函数返回结果错误,以及函数执行的性能问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值