2个数仓中不等值关联优化案例
本文分享自华为云社区《GaussDB(DWS)性能调优:不等值关联优化》,作者: 门前一棵葡萄树。
场景1
使用场景:本案例适合满足以下条件的场景
- 关联条件使用OR连接
- 关联条件中使用同一列做数据筛选
原始语句
SELECT t2.PARTNER_CHANNEL_CODE AS CHANNEL_ID ,t1.COUNTRY_CODE ,t1.BRAND ,t2.CHANNEL_ID AS CHANNEL_ID2 FROM t1 LEFT JOIN t2 ON ( t2.CHANNEL_ID = t1.CHANNEL_ID AND t1.TYPE = 'DR' ) OR ( t2.PARTNER_CHANNEL_CODE = t1.CHANNEL_ID AND t1.TYPE = 'ALL' ) GROUP BY t2.PARTNER_CHANNEL_CODE ,t1.COUNTRY_CODE ,t1.BRAND ,t2.CHANNEL_ID
性能分析
通过查询计划分析发现,t1表和t2表关联走了NEST LOOP,查询整体耗时45S,NEST LOOP耗时占用整个查询执行耗时的96%。因此考虑能否通过SQL改写或HINT规避NEST LOOP。观察发现t1表和t2表包含两个关联关联条件,两个关联条件之间使用OR连接,属于非等值关联,因此不能走HASH JOIN。进一步分析SQL发现两个关联条件中都使用t1.TYPE进行过滤筛选:
(t2.CHANNEL_ID = t1.CHANNEL_ID AND t1.TYPE='DR') OR (t2.PARTNER_CHANNEL_CODE = t1.CHANNEL_ID AND t1.TYPE='ALL' )
该关联条件包含以下三种关联组合:
- t1表中t1.TYPE='DR'的行,只能使用第一个关联条件与t2表关联;
- t1表中t1.TYPE='ALL'的行,只能使用第二个关联条件与t2表关联;
- t1表中t1.TYPE NOT IN ('ALL','DR')的行,不与t2表关联,直接补空。
t1表中的一行数据只能选择这三个关联条件中的一个与t2表关联,因此该关联条件可以改写为不同关联条件的UNION ALL(UNION会去重,不等价)。
优化改写
改写后SQL如下所示:
SELECT CHANNEL_ID ,COUNTRY_CODE ,BRAND ,CHANNEL_ID FROM ( SELECT t2.PARTNER_CHANNEL_CODE AS CHANNEL_ID ,t1.COUNTRY_CODE ,t1.BRAND ,t2.CHANNEL_ID AS CHANNEL_ID2 FROM t1 LEFT JOIN t2 ON t2.CHANNEL_ID = t1.CHANNEL_ID WHERE t1.TYPE = 'DR' UNION ALL SELECT t2.PARTNER_CHANNEL_CODE AS CHANNEL_ID ,t1.COUNTRY_CODE ,t1.BRAND ,t2.CHANNEL_ID AS CHANNEL_ID2 FROM t1 t2 ON t2.PARTNER_CHANNEL_CODE = t1.CHANNEL_ID WHERE t1.TYPE='ALL' UNION ALL SELECT t2.PARTNER_CHANNEL_CODE AS CHANNEL_ID ,t1.COUNTRY_CODE ,t1.BRAND ,t2.CHANNEL_ID AS CHANNEL_ID2 FROM t1 LEFT JOIN t2 ON FALSE WHERE t1.TYPE NOT IN ('ALL','DR') ) GROUP BY CHANNEL_ID,COUNTRY_CODE,BRAND,CHANNEL_ID
改写后SQL变为三个子查询的UNION ALL,执行时间缩减至1s以内,性能优化45倍。
场景二
使用场景:本案例适合满足以下条件的场景
- 大表A不等值关联小表B
- B的等值关联字段为主键
【原始语句】
SELECT T.CREATE_INVOICE_USER, T.PERIOD_ID, T.AP_INVOICE_ID, T.AP_INVOICE_NUM, T.AP_BATCH_NAME, EMP1.EMPLOYEE_NO, EMP1.EMPLOYEE_NAME FROM DWACTDI.DWR_AP_GLOBAL_INVOICE_DETAIL_F_I T LEFT JOIN DWRDIM_DW1.DWR_DIM_EMPLOYEE_D EMP1 ON (EMP1.SCD_ACTIVE_IND = 1 AND(T.CREATE_INVOICE_USER = EMP1.EMPLOYEE_NO OR SUBSTR(T.CREATE_INVOICE_USER, 2) = EMP1.EMPLOYEE_NO))
【性能分析】
原始语句执行超时(超过1h),执行计划如下。可以看到执行语句存在大表NestLoop操作
分析发现表dwrdim_dw1.dwr_dim_employee_d是维度表,且关联列employee_no是主键
【优化改写】
SELECT T.CREATE_INVOICE_USER, T.PERIOD_ID, T.AP_INVOICE_ID, T.AP_INVOICE_NUM, T.AP_BATCH_NAME, nvl(EMP1_0.EMPLOYEE_NO, EMP1_1.EMPLOYEE_NO) AS EMPLOYEE_NO, nvl(EMP1_0.EMPLOYEE_NAME, EMP1_1.EMPLOYEE_NAME) AS ERP_ACCOUNTANT_ENAME FROM DWACTDI.DWR_AP_GLOBAL_INVOICE_DETAIL_F_I T LEFT JOIN DWRDIM_DW1.DWR_DIM_EMPLOYEE_D EMP1_0 ON (EMP1_0.SCD_ACTIVE_IND = 1 AND(T.CREATE_INVOICE_USER = EMP1_0.EMPLOYEE_NO)) LEFT JOIN DWRDIM_DW1.DWR_DIM_EMPLOYEE_D EMP1_1 ON (EMP1_1.SCD_ACTIVE_IND = 1 AND(SUBSTR(T.CREATE_INVOICE_USER, 2) = EMP1_1.EMPLOYEE_NO))
改写后执行信息如下

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
ZGC关键技术分析
一、引言 垃圾回收对于Javaer来说是一个绕不开的话题,工作中涉及到的调优工作也经常围绕垃圾回收器展开。面对不同的业务场景没有一个统一的垃圾回收器能保证可GC性能。因此对程序员来说不仅要会编写业务代码,同时也要卷一下JVM底层原理和调优知识。这种局面可能因为ZGC的出现而发生改变,新一代回收器ZGC几乎不需要调优的情况下GC停顿时间可以降低到亚秒级。 Oracle从JDK11开始正式引入ZGC,ZGC设计三大目标: 支持TB级内存 (8M~4TB) 。 停顿时间控制在10ms之内 (生产环境实际观测在微秒级) ,停顿不会随着堆的大小,或者活跃对象的大小而增加。 对程序吞吐量影响小于15%。 ZGC是如何设计怎么达到这个目标的呢?本文将从ZGC算法的关键特性入手,通过分析ZGC周期处理过程来理解这些特性,探索ZGC设计思想。 二、ZGC术语 非分代:将对内存划分为新生代和老年代 (G1已经逻辑分代) ,ZGC取消分代设计,每个GC周期都将标记整个堆中的所有活动对象。 页面: ZGC将堆空间分解成一块块区域,这些区域叫做页面,ZGC通过页面来回收内存。 并发性: GC和线程和业务线程同时...
- 下一篇
对抗软件复杂度的战争
一、何为研发效能? 当我们谈研发效能的时候,我们在谈些什么?这个议题被抛出来,有人讨论,是因为存在问题,问题就在于实际的研发效率,已经远低于预期了。企业初创的时候,一个想法从形成到上线,一个人花两个小时就完成了,而当企业发展到数千人的时候,类似事情的执行,往往需要多个团队,花费好几周才能完成。这便造成了鲜明的对比,而这一对比产生的印象,对于没有深入理解软件工程的人来说,显得难以理解,可又往往无计可施。 细心的读者会留意到,前文我既用了“效能”一词,也用了“效率”一词。这是为了做严谨的区分,效能往往是用来衡量产品的经济绩效,而效率仅仅是指提升业务响应能力,提高吞吐,降低成本。 这里的定义引用了乔梁的《如何构建高效能研发团队》课程材料,本文并不讨论产品开发方法,因此后面的关注都在“效率”上。 本世纪 10 年代,早期的互联网从业者开发简易网站的时候,只需要学会使用 Linux、Apache、MySql、PHP(Perl)即可,这套技术有一个好记的名字:LAMP。可今天,在一个大型互联网公司工作的开发者,需要理解的技术栈上升了一个数量级,例如分布式系统、微服务、Web 开发框架、DevOps...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Red5直播服务器,属于Java语言的直播服务器