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

转载自GBASE南大通用官方社区:https://www.gbase.cn/community/post/3753

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~~


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容