简介: ods层数据同步时经常会遇到增全量合并的模型,即T-1天增量表 + T-2全量表 = T-1全量表。可以通过full outer join脚本来完成合并,但是数据量很大时非常消耗资源。本文将为您介绍在做增量数据的增加、更新时如何通过full outer join改写left anti join来实现的最佳实践。

背景

ods层数据同步时经常会遇到增全量合并的模型,即T-1天增量表 + T-2全量表 = T-1全量表。可以通过full outer join脚本来完成合并,但是数据量很大时非常消耗资源。

insert overwrite table tb_test partition(ds='${bizdate}')
select case when a.id is not null then a.id esle b.id end as id   ,if(a.name is not null, a.name, b.name) as name,coalesce(a.age, b.age) as age --这3种写法一样,都是优先取delta表的字段from
(select * from tb_test_delta where ds='${bizdate}'
) a
full outer join
(select * from tb_test where ds='${bizdate-1}'
) b
on a.id =b.id;

这种写法可实现新增和更新操作:

  • 新增是指增量表中新出现的数据,而全量表中没有;
  • 更新是指增量表和全量表中都有的数据,但优先取增量表的数据,覆盖历史表的数据。
    如下图所示,R2_1是增量表当天去重后增量数据,M3是全量表前一天的数据,而J4_2_3则是full outer join的执行图。

将J4_2_3展开会发现里面将增量和全量进行了merge join,当数据量很大(1288亿条)时会产生很大的shuffle开销。此时优化方案就是将full outer join改成 union all,从而避免join shuffle

优化模型

结论:full outer join改成hash cluster + left join +union all可以有效地降低计算成本,且有两种应用场景。先将模型进行抽象,假设有a和b两个表,a是增量表,b是全量表:

with a as ( select * from values  (1,'111'),(2,'two'),(7,'777') as (id,name) ) --增量,b as ( select * from values  (1,''),(2,'222'),(3,'333'),(4,'444') as (id,name) )  --全量

场景1:只合并新增数据到全量表

left anti join相当于not in,增量not in全量,过滤后只剩下完全新增的id,对全量中已有的id不修改:

--查询完全新增的id
select * from a left anti join b on a.id=b.id ;
--结果如下
+------------+------+
| id         | name |
+------------+------+
| 7          | 777  |
+------------+------+
--完全新增的合并全量表
select * from  a --增量表
left anti join b on a.id=b.id
union all
select * from b  --全量表
--结果如下
+------------+------+
| id         | name |
+------------+------+
| 1          |      |
| 2          | 222  |
| 3          | 333  |
| 4          | 444  |
| 7          | 777  |
+------------+------+

场景2:合并新增数据到全量表,且更新历史数据

全量not in增量,过滤后只剩下历史的id,然后union all增量,既新增也修改

--查询历史全量数据
select * from b left anti join a on a.id=b.id;
--结果如下
+------------+------+
| id         | name |
+------------+------+
| 3          | 333  |
| 4          | 444  |
+------------+------+
--合并新增数据到全量表,且更新历史数据
select * from  b --全量表
left anti join a on a.id=b.id
union all
select * from a ; --增量表
--结果如下
+------------+------+
| id         | name |
+------------+------+
| 1          | 111  |
| 2          | two  |
| 7          | 777  |
| 3          | 333  |
| 4          | 444  |
+------------+------+

优化实践

步骤1:表属性修改

表、作业属性修改,对原来的表、作业进行属性优化,可以提升优化效果。

set odps.sql.reducer.instances=3072;  --可选。默认最大1111个reducer,1111哈希桶。
alter table table_name clustered by(contact_id) sorted by(contact_id) into 3072 buckets;--必选

步骤2:按照上述模型的场景1 或者 场景2进行代码改造。

这里先给出代码改造后的资源消耗对比:

原来的full outer jion left anti join初始化 原来的full outer jion left anti join第二天以后
时间消耗 8h30min38s 1h4min48s 7h32min30s 32min30s
cpu消耗 29666.02 Core * Min 65705.30 Core * Min 31126.86 Core * Min 30589.29 Core * Min
mem消耗 109640.80 GB * Min 133922.25 GB * Min 114764.80 GB * Min 65509.28 GB * Min

可以发现hash cluster分桶操作在初始化有额外的开销,主要是按主键进行散列和排序,但是这是值得的,可一劳永逸,后续的读取速度非常快。以前每天跑需要8小时,现在除了分桶初始化需要1小时,以后每天实际只需要30分钟。

初始化执行图

图1:

  • M2是读全量表。
  • M4是读取增量表,在场景2的模型中增量表被读取了两次,其中:

    • R5_4是对主键去重(row_number)后用于后面的union all,里面包含了所有的增量数据;
    • R1_4是对主键去重(row_number)后用于left anti join,里面只包含了主键。
  • J3_1_2是left anti join,将它展开后看到这里还是有mergJoin,但是这只是初始化的操作,后面每天就不会有了。展开后如图2。
  • R6_3_5是将增量和全量进行union all,展开后如图3。
  • R7_6则是将索引信息写入元数据,如图3的MetaCollector1会在R7_6中sink。
    因此:图1中除了R5_4和R1_4是去重必须的,有shuffle。还有J3_1_2和R6_3_5这两个地方有shuffle。

图2:

图3:

第二天以后的执行图

图1:

同上,图1中的R3_2和R1_2是对增量去重必要对操作,有shuffle,这里忽略。

初始化执行图的J3_1_2和R6_3_5已经被合并到了M4_1_3,将其展开后如图2。即left anti join 和 union all这两步操作在一个阶段完成了,且这个阶段是Map 任务(M4_1_3),而不是Join任务或Reduce任务。而且全量表不在单独占用一个Map任务,也被合并到了M4_1_3,因此整个过程下来没有shuffle操作,速度提升非常明显。也就是说只需要一个M4_1_3就能完成所有到操作,直接sink到表。

R5_4则是将索引信息写入元数据,如图2的MetaCollector1会在R5_4中sink。

图2:

原文链接
本文为阿里云原创内容,未经允许不得转载。

MaxCompute full outer join改写left anti join实践相关推荐

  1. Hive中的left semi join和left anti join

    ​LEFT SEMI JOIN 这个大家应该知道的人相对少些,LEFT SEMI JOIN 只会返回匹配右表的数据,而且 LEFT SEMI JOIN 只会返回左表的数据,右表的数据是不会显示的 举例 ...

  2. Null Aware Anti Join 速记

    所谓 semi join,指的是 join 的两张表里只输出其中一侧,另一侧用于计算输出条件.通常,我们把输出侧叫"保留侧",条件侧叫"非保留侧". Tips: ...

  3. 图解SQL的inner join(join)、left join、right join、full outer join、union、union all的区别...

    对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚.Codin ...

  4. oracle+semijoin,Semi join 与anti join

    1.semi join Oracle在处理exists或in的时候,会使用semi join的连接方式: sys@EBANK>select object_name,object_type fro ...

  5. Oracle的join默认为,oracle join用法

    文章分类:数据库 join用法 条件连接(join) T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 ON boolean_expre ...

  6. sql join 示例_SQL CROSS JOIN与示例

    sql join 示例 In this article, we will learn the SQL CROSS JOIN concept and support our learnings with ...

  7. sql join on和不用join区别_图解 SQL 各种 JOIN,太有用了!

    点击上方蓝字关注小姐姐吧从业以来主要在做客户端,用到的数据库都是表结构比较简单的 SQLite,以我那还给老师一大半的 SQL 水平倒也能对付.现在偶尔需要到后台的 SQL Server 里追查一些数 ...

  8. 面试官:说说left join和left semi join 两者有什么区别?

    张工是一名程序员,主要是做java开发,有次到一家软件公司面试软件开发岗位,面试官问了他两个问题,其中有一个问题是这样的这样: 说说left join和left semi join 有什么区别? 对于 ...

  9. 【转载】SQL中使用update inner join和delete inner join

    原文地址:SQL中使用update inner join和delete inner join Update XXX set XXX where 这种写法大家肯定都知道,才发现update和delete ...

最新文章

  1. 李彦宏乌镇谈人工智能:百度会很快和雄安宣布一个大的智能城市计划
  2. 两年伯克利数学博士毕业,蝉联阿里数学竞赛金奖,张钺:我就是个普通人
  3. [WCF编程]2.SOA概述
  4. VB 6.0中如何访问EXCEL 2007及EXCEL 2010
  5. 租车信息系统数据库设计(3)
  6. 遍历一个数据去掉最后一个元素的样式
  7. SCA/SDO与WCF的比较
  8. 再想想-----***
  9. catboost特征重要性_一文讲解特征工程!经典外文PPT及中文解析
  10. php foreach 时间,PHP利用for,while,foreach遍历时间比较的简单示例
  11. 使用Python教你秒搭本地服务器
  12. lisp 获取横断面数据_AutoCADLISP二次开发辅助道路横断面测量成果检查
  13. 有什么什么比较好用又不流氓的独立的弹窗拦截软件?这4款App让你杜绝流氓软件弹窗
  14. 解决 zbrush导出的模型在blender里没有颜色的问题
  15. “巴巴罗莎计划---我的崛起之路
  16. PanDownload作者被抓,为何大家都对百度网盘如此气愤?
  17. 软件需求、架构培训(一)
  18. linux相关的东东,来自dbanotes
  19. 修改element-UI 的 el-upload样式
  20. 手机上php视频格式怎么转成mp4,我想知道手机上用爱奇艺下的视频怎么转换成MP4格式...

热门文章

  1. 在matlab中求协方差,matlab里面的求协方差函数
  2. ug使用服务器系统,ug服务器设置教程视频
  3. c语言栈指针移动原理,C指针原理(4)-ATamp;T汇编
  4. a股历史30年的大盘价_2020年7月30日大盘走势分析
  5. 双水泵轮换工作原理图_一用一备式冷凝水泵应急电源的设计与实现
  6. 字节跳动测试开发4轮面试_字节跳动测试开发工程师一面总结
  7. 【LeetCode笔记】54. 螺旋矩阵(Java、迭代、递归)
  8. xp 4g内存补丁_32位操作系统导致电脑可用内存不足4G
  9. itools 不支持缩略图下载_PS插件缩略图3.8.0.96安装教程
  10. python的setting怎么找_django项目的配置文件settings.py详解