函数迁移到南大通用GBase 8c的技巧一则

2024年5月的某天早上,客户发来如下的问候:

南大通用GBase 8c的DBA们,早上好,项目遇到一个SQL查询的问题,想要请教下,当一个SQL的select部分存在函数时,是否是先用函数计算结果,再计算where条件的结果?

其实这个问题本身问的有些模糊,但客户马上又补充道:

目前有个SQL,在有函数,和没有函数的情况下,查询速度差异巨大,有函数执行要9秒钟,没有函数的时候0.05秒就执行完了。但之前在Oracle下执行是很快的。


南大通用GBase 8c在分布式形态部署下,既有强大的并行处理能力,又可以保证分布式事务的实时一致性,通常情况下都能够达到比Oracle等传统集中式数据库更快的性能。

那么……

先看看具体SQL——
SELECT
	compare_date ( '2024-05-23 17:32:01', T.START_TIME ) AS START_TIME1,
	compare_date ( '2024-05-23 17:32:01', T.END_TIME ) AS END_TIME1 
FROM
	(
	SELECT
		acc.res_id,
		authz.START_TIME,
		authz.END_TIME,
		authz.FOREVER_TIME AS FOREVER_TIME1 
	FROM
		u_oper_authz authz
		INNER JOIN u_res_account acc ON authz.target_id = acc.ID 
	WHERE
		authz.auth_type = 'resAccount' 
		AND authz.user_id = '673487257655296' 
		AND authz.tenant = 'fe0307d50b584aacbe283cc9600419d7' 
		AND authz.LOGIC_DELETE = '0' 
	AND acc.LOGIC_DELETE = '0' 
	) T

经过几轮对话,客户的疑问其实在于compare_date ( '2024-05-23 17:32:01', T.START_TIME ) 这个函数,如果只查询T.START_TIMET.END_TIME速度很快,但如果带上compare_date 函数就很慢。

而且在Oracle下执行没有问题,为什么迁移到分布式架构的南大通用GBase 8c上就会有问题呢?

其实经验丰富的8c DBA们看到这里已经可以判断出问题所在了,但这的确又是函数从Oracle这类传统集中式架构数据库中迁移到南大通用GBase 8c分布式形态时的常见问题。

再看看执行计划——
有函数时
Hash Join  (cost=107938.71..166726.88 rows=1037 width=38)
 Hash Cond: ((authz.target_id)::text = (acc.id)::text)
 ->  Data Node Scan on u_oper_authz "_REMOTE_TABLE_QUERY_"  (cost=0.00..0.00 rows=1000 width=71)
       Node/s: All datanodes
       ->  Index Scan using idx_uoperauthz_userid on u_oper_authz authz  (cost=0.00..257.80 rows=117 width=71)
             Index Cond: ((user_id)::text = '673487257655296'::text)
             Filter: (((auth_type)::text = 'resAccount'::text) AND ((tenant)::text = 'fe0307d50b584aacbe283cc9600419d7'::text) AND ((logic_delete)::text = '0'::text))
 ->  Hash  (cost=0.00..0.00 rows=1000 width=33)
       ->  Data Node Scan on u_res_account "_REMOTE_TABLE_QUERY_"  (cost=0.00..0.00 rows=1000 width=33)
             Node/s: All datanodes
             ->  Seq Scan on u_res_account acc  (cost=0.00..85746.60 rows=1321708 width=33)
                   Filter: ((logic_delete)::text = '0'::text)

没有函数时
Streaming(type: GATHER)  (cost=0.00..444.62 rows=173 width=72)
  Spawn on: All datanodes
  ->  Nested Loop  (cost=0.00..440.67 rows=1037 width=72)
        ->  Streaming(type: REDISTRIBUTE)  (cost=0.00..273.37 rows=720 width=72)
              Spawn on: All datanodes
              ->  Index Scan using idx_uoperauthz_userid on u_oper_authz authz  (cost=0.00..263.47 rows=720 width=72)
                    Index Cond: ((user_id)::text = '673487257655296'::text)
                    Filter: (((auth_type)::text = 'resAccount'::text) AND ((tenant)::text = 'fe0307d50b584aacbe283cc9600419d7'::text) AND ((logic_delete)::text = '0'::text))
        ->  Index Scan using u_res_account_pkey on u_res_account acc  (cost=0.00..1.38 rows=1 width=66)
              Index Cond: ((id)::text = (authz.target_id)::text)
              Filter: ((logic_delete)::text = '0'::text)


可以看到,在没有函数时,执行计划走的是Stream。

这里就需要再插播一下南大通用GBase 8c分布式形态下的部署架构了

分布式形态的GBase 8c

GBase 8c数据库分布式形态采用share nothing的分布式架构,计算节点和存储节点分离,节点间通过高速网络进行通信,所有节点都有主从互备,确保系统的高可用性。由于没有资源共享,增加节点就可以线性地扩展集群的存储能力和计算能力,满足业务规模增长的要求。

GBase 8c支持SQL透传、SQL 下推、执行计划下推、数据上拉多种分布式查询执行方式,可根据实际的SQL命令自动选择最高效的执行方式,从而提高了分布式查询的执行效率。

问题根因

所以这次问题的真正原因,在于compare_date这个函数影响了该SQL的下推,并没有把该函数下推到DN节点去并行执行,而是把所有数据上拉到CN节点统一执行,最终造成了执行时间上近200倍的差距。

算子下推是GBase 8c关键技术之一,可以把各种复杂的SQL进行下推执行,最小化数据移动,这是相对于基于分库分表的中间件方案的核心优势。

最后看看这个“罪魁祸首”函数——

compare_date函数定义

CREATE OR REPLACE FUNCTION public.compare_date(s_date character varying, t_date character varying)
 RETURNS integer
 LANGUAGE plpgsql
 NOT FENCED NOT SHIPPABLE
AS $function$

BEGIN

 IF(to_timestamp(trim(s_date),'yyyy-mm-dd hh24:mi:ss') > to_timestamp(trim(t_date),'yyyy-mm-dd hh24:mi:ss')) then

    RETURN 1;

ELSE RETURN - 1;

END IF;

EXCEPTION
   WHEN others THEN RETURN - 2;
END;
$function$;

这里最关键的是第4行的 NOT SHIPPABLE

在GBase 8c中,使用SHIPPABLENOT SHIPPABLE来表示该函数是否可以下推到DN上执行,当前函数中使用的 NOT SHIPPABLE,意味着不允许下推到DN节点去并行处理,而是要把所有DN节点上的数据汇总拉到CN节点后,再在CN节点对全部数据进行函数运算操作。显然无论计算资源还是网络传输方面都需要有相应的投入。

SHIPPABLE则可以将函数下推到DN上执行,可以实现并行处理,同时由于全量数据已经分散到多个DN节点上,因此并行处理的结果集更小,从而达到近200倍的性能提升。

一个函数是否允许下推,就要看函数具体的业务逻辑是否必须要在全量数据集上运算。对于本问题中的函数,本意是单独对每一个值进行日期比较的计算,并不涉及聚合操作,因此完全可以去掉NOT,改为SHIPABLE,从而将函数计算下推到DN节点执行。

问题解决

改为SHIPPABLE后,客户再次执行,可以看到右下角运行时间为 0.054s,基本与不用函数时间一致,可见函数已经下推,且函数实际执行耗时也并不高。


 

欢迎大家多多试用性能强大,又支持强一致性分布式事务的南大通用GBase 8c~~
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值