精华内容
下载资源
问答
  • 倾斜的解释
    2019-03-26 08:42:19

    Map join引起的数据倾斜问题的解释
    普通的join,那么肯定要走shuffle,那么普通的join 肯定走的是reduce join
    先将所有相同的key,对应的values,汇聚到一个task中,然后再进行join。
    将reduce join转换为map join。

    spark中 如果两个RDD要进行join,其中一个RDD是比较小的。一个RDD是一百万数据,一个RDD是一万数据。
    如果一个RDD很小 broadcast(广播变量出去的那个小数据以后,就会在每个executor manager中都驻留一份。要确保你的内存)

    正常join是在reduce端join 会经过shuffle 数据重新分区以后会产生数据倾斜 如果map join把小表缓存在内存中 直接在map端进行计算 出结果 不会产生shuffle过程 所以会解决 数据倾斜问题

    更多相关内容
  • 什么是数据倾斜 ** 我们在用hive取数的时候,有的时候只是跑一个简单的join语句,但是却跑了很长的时间,有的时候我们会觉得是集群资源不够导致的,但是很大情况下就是出现了"数据倾斜"的情况。 在了解数据倾斜之前...

    **

    什么是数据倾斜

    **

    我们在用hive取数的时候,有的时候只是跑一个简单的join语句,但是却跑了很长的时间,有的时候我们会觉得是集群资源不够导致的,但是很大情况下就是出现了"数据倾斜"的情况。

    在了解数据倾斜之前,我们应该有一个常识,就是现实生活中的数据分布是不均匀的,俗话说"28定理",80%的财富集中在20%的人手中之类的故事相信大家都看得不少。所以,在我们日常处理的现实数据中,也是符合这种数据分布的,数据倾斜一般有两种情况:

    变量值很少: 单个变量值的占比极大,常见的字段如性别、学历、年龄等。
    变量值很多: 单个变量值的占比极小,常见的字段如收入、订单金额之类的。
    数据倾斜,在MapReduce编程模型中十分常见,就是大量的相同key被partition分配到一个分区里,造成了"一个人累死,其他人闲死"的情况,这违背了并行计算的初衷,整体的效率是十分低下的。

    数据倾斜的原因
    当我们看任务进度长时间维持在99%(或100%),查看任务监控页面就会发现只有少量(1个或几个)reduce子任务未完成。因为其处理的数据量和其他reduce差异过大,这就是数据倾斜的直接表现。

    而导致这个的原因,大致可以分为下面几点

    key分布不均匀
    业务数据本身的特性
    建表时考虑不周
    某些SQL语句本身就有数据倾斜
    具体可以体现在下面的常见操作:
    备注:图片文字内容来自网络

    Hadoop计算框架的特点
    在了解如何避免数据倾斜之前,我们先来看看Hadoop框架的特性:

    大数据量不是大问题,数据倾斜才是大问题;
    jobs数比较多的作业效率相对比较低,比如即使有几百万的表,如果多次关联多次汇总,产生十几个jobs,耗时很长。原因是map reduce作业初始化的时间是比较长的;
    sum,count,max,min等UDAF(User Defined Aggregate Function:自定义函数),不怕数据倾斜问题,hadoop在map端的汇总并优化,使数据倾斜不成问题;
    count(distinct),在数据量大的情况下,效率较低,如果是多count(distinct)效率更低,因为count(distinct)是按group by字段分组,按distinct字段排序,一般这种分布式是很倾斜的,比如男uv,女uv,淘宝一天30亿的pv,如果按性别分组,分配2个reduce,每个reduce处理15亿数据。

    ✌️ 优化的常用手段
    说的是优化手段,但更多的是"踩坑"的经验之谈。

    ☝️ 优化之道:
    首先要了解数据分布,自己动手解决数据倾斜问题是个不错的选择;
    增加jvm(Java Virtual Machine:Java虚拟机)内存,这适用于变量值非常少的情况,这种情况下,往往只能通过硬件的手段来进行调优,增加jvm内存可以显著的提高运行效率;

    增加reduce的个数,这适用于变量值非常多的情况,这种情况下最容易造成的结果就是大量相同key被partition到一个分区,从而一个reduce执行了大量的工作;
    
    重新设计key,有一种方案是在map阶段时给key加上一个随机数,有了随机数的key就不会被大量的分配到同一节点(小几率),待到reduce后再把随机数去掉即可;
    

    使用combiner合并。combinner是在map阶段,reduce之前的一个中间阶段,在这个阶段可以选择性的把大量的相同key数据先进行一个合并,可以看做是local reduce,然后再交给reduce来处理,减轻了map端向reduce端发送的数据量(减轻了网络带宽),也减轻了map端和reduce端中间的shuffle阶段的数据拉取数量(本地化磁盘IO速率);(hive.map.aggr=true)设置合理的map reduce的task数,能有效提升性能。(比如,10w+级别的计算,用160个reduce,那是相当的浪费,1个足够);数据量较大的情况下,慎用count(distinct),count(distinct)容易产生倾斜问题;hive.groupby.skewindata=true有数据倾斜的时候进行负载均衡,当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

    ✌️ SQL语句调节:

    如何Join:
    关于驱动表的选取,选用join key分布最均匀的表作为驱动表;
    做好列裁剪和filter操作,以达到两表做join的时候,数据量相对变小的效果。

    大小表Join:
    使用map join让小的维度表(1000条以下的记录条数) 先进内存。在map端完成reduce。

    大表Join大表:
    把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果。
    count distinct大量相同特殊值:
    count distinct时,将值为空的情况单独处理,如果是计算count distinct,可以不用处理,直接过滤,在最后结果中加1。如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union。

    group by维度过小:
    采用sum() group by的方式来替换count(distinct)完成计算。
    特殊情况特殊处理:

    在业务逻辑优化效果的不大情况下,有些时候是可以将倾斜的数据单独拿出来处理。最后union回去。

    看完上面的经验总结还是有点懵逼?说实话我也是的,太多的信息量冲击,不过我们可以收藏起来以后继续看多几次,加深印象。

    接下来,我们将从一些具体的案例来讲讲SQL语句优化的技巧,非常常用,对我们日常写SQL很有帮助。

    优化案例
    场景1:RAC常用(real application clusters的缩写,译为“实时应用集群”)

    有一张user表,为卖家每天收入表,user_id,dt(日期)为key,属性有主营类目(cat),指标有交易金额,交易比数。每天要取每个user的主营类目在过去10天的总收入,总比数。

    常规做法:取每个user_id最近一天的主营类目,存入临时表t1,汇总过去10天的总交易金额,交易比数,存入临时表t2,连接t1,t2,得到最终的结果。

    优化做法:
    SELECT user_id
    , substr(MAX(concat(dt, cat)), 9) AS main_cat
    , SUM(qty), SUM(amt)
    FROM users
    WHERE dt BETWEEN 20101201 AND 20101210
    GROUP BY user_id;
    场景2:空值产生的数据倾斜(最常见的现象)

    日志中,常会有信息丢失的问题,比如全网日志中的 user_id,如果取其中的 user_id 和 bmw_users 关联,会碰到数据倾斜的问题。

    解决方式1:user_id为空的不参与关联

    SELECT *
    FROM log a
    JOIN bmw_users b
    ON a.user_id IS NOT NULL
    AND a.user_id = b.user_id
    UNION ALL
    SELECT *
    FROM log a
    WHERE a.user_id IS NULL;

    解决方式2:赋与空值分新的key值

    SELECT *
    FROM log a
    LEFT JOIN bmw_users b ON CASE
    WHEN a.user_id IS NULL THEN concat(‘dp_hive’, rand())
    ELSE a.user_id
    END = b.user_id;

    结论:方法2比方法1效率更好,不但io少了,而且作业数也少了。解决方法1 log表被读取了两次,jobs是2。这个优化适合无效 id (比如 -99 , ’’, null 等) 产生的倾斜问题。把空值的 key 变成一个字符串加上随机数,就能把倾斜的数据分到不同的reduce上 ,解决数据倾斜问题。

    场景3:不同数据类型关联产生数据倾斜

    一张表 s8_log,每个商品一条记录,要和商品表关联。但关联却碰到倾斜的问题。s8_log 中有字符串商品 id,也有数字的商品 id。字符串商品 id 类型是 string 的,但商品中的数字 id 是 bigint 的。问题的原因是把 s8_log 的商品 id 转成数字 id 做 Hash(数字的 Hash 值为其本身,相同的字符串的 Hash 也不同)来分配 Reducer,所以相同字符串 id 的 s8_log,都到一个 Reducer 上了。

    解决方式:把数字类型转换成字符串类型

    SELECT *
    FROM s8_log a
    LEFT JOIN r_auction_auctions b ON a.auction_id = CAST(b.auction_id AS string);
    场景4:多表 union all 会优化成一个 job

    推广效果表要和商品表关联,效果表中的 auction id 列既有商品 id,也有数字 id,和商品表关联得到商品的信息。

    SELECT *
    FROM effect a
    JOIN (
    SELECT auction_id AS auction_id
    FROM auctions
    UNION ALL
    SELECT auction_string_id AS auction_id
    FROM auctions
    ) b
    ON a.auction_id = b.auction_id;

    结论:这样子比分别过滤数字 id,字符串 id ,然后分别和商品表关联性能要好。这样写的好处:1个 MR 作业,商品表只读取一次,推广效果表只读取一次。把这个 sql 换成 MR 代码的话,map 的时候,把 a 表的记录打上标签 a ,商品表记录每读取一条,打上标签 t,变成两个<key,value> 对,<t,数字id,value>,<t,字符串id,value>。所以商品表的 HDFS(Hadoop Distributed File System) 读只会是一次。

    场景5:消灭子查询内的 group by

    原写法:
    SELECT *
    FROM (
    SELECT *
    FROM t1
    GROUP BY c1, c2, c3
    UNION ALL
    SELECT *
    FROM t2
    GROUP BY c1, c2, c3
    ) t3
    GROUP BY c1, c2, c3;

    优化写法:
    SELECT *
    FROM (
    SELECT *
    FROM t1
    UNION ALL
    SELECT *
    FROM t2
    ) t3
    GROUP BY c1, c2, c3;

    结论:从业务逻辑上说,子查询内的 group by 功能与外层的 group by 重复,除非子查询内有 count(distinct)。经过测试,并未出现 union all 的 hive bug,数据是一致的。MR 的作业数由3减少到1。t1 相当于一个目录,t2 相当于一个目录,对map reduce程序来说,t1,t2 可以做为 map reduce 作业的 mutli inputs。这可以通过一个 map reduce 来解决这个问题。Hadoop的计算框架,不怕数据多,怕作业数多。

    场景6:消灭子查询内的count(distinct),max,min

    原写法:

    SELECT c1, c2, c3, sum(pv)
    FROM (
    SELECT c1, c2, c3, COUNT(c4)
    FROM t1
    GROUP BY c1, c2, c3
    UNION ALL
    SELECT c1, c2, c3, COUNT(DISTINCT c4)
    FROM t2
    GROUP BY c1, c2, c3
    ) t3
    GROUP BY c1, c2, c3;
    这种我们不能直接union 再groupby,因为其中有一个表的操作用到了去重,这种情况,我们可以通过建立临时表来消灭这种数据倾斜问题。

    优化写法:

    INSERT INTO t4
    SELECT c1, c2, c3, COUNT(DISTINCT c4)
    FROM t2
    GROUP BY c1, c2, c3;

    SELECT c1, c2, c3, SUM(pv)
    FROM (
    SELECT c1, c2, c3, COUNT(c4)
    FROM t1
    UNION ALL
    SELECT *
    FROM t4
    ) t3
    GROUP BY c1, c2, c3;

    场景7:两张大表join

    有两张表,一张是用户访问日志表log,一张是用户表users,其中log表上T,user表也上G,如何每日做到快速连接呢?

    解决方法:

    SELECT *
    FROM log a
    LEFT JOIN (
    SELECT d.*
    FROM (
    SELECT DISTINCT memberid
    FROM log
    ) c
    JOIN users d ON c.memberid = d.memberid
    ) x
    ON a.memberid = b.memberid;

    上面代码的意思,就是我们可以通过缩小主键的范围来达到减少表的连接操作,比如说限值某段时间,这样子,memberid就会有所减少了,而不是全量数据。

    场景8:reduce的时间过长

    还是场景7的例子,假设一个memberid对应的log里有很多数据,那么最后合并的时候,也是十分耗时的,所以,这里需要找到一个方法来解决这种reduce分配不均的问题。

    解决方法:

    SELECT *
    FROM log a
    LEFT JOIN (
    SELECT memberid, number
    FROM users d
    JOIN num e
    ) b
    ON a.memberid = b.memberid
    AND mod(a.pvtime, 30) + 1 = b.number;

    解释一下,上面的num是一张1列30行的表,对应1-30的正整数,把users表膨胀成N份(基于倾斜程度做一个合适的选择),然后把log数据根据memberid和pvtime分到不同的reduce里去,这样可以保证每个reduce分配到的数据可以相对均匀。

    场景9:过多的where条件

    有的时候,我们会写超级多的where条件来限制查询,其实这样子是非常低效的,主要原因是因为这个and条件hive在生成执行计划时产生了一个嵌套层次很多的算子。

    解决方案:

    1)把筛选条件对应的值写入一张小表,再一次性join到主表;

    2)或者写个udf(user-defined function,用户定义函数),把这些预设值读取进去,udf来完成这个and数据过滤操作。

    场景10:分组结果很多,但是你只需要topK

    原写法:

    SELECT mid, url, COUNT(1) AS cnt
    FROM (
    SELECT *
    FROM r_atpanel_log
    WHERE pt = ‘20190610’
    AND pagetype = ‘normal’
    ) subq
    GROUP BY mid, url
    ORDER BY cnt DESC
    LIMIT 15;

    优化写法:

    SELECT *
    FROM (
    SELECT mid, url, COUNT(1) AS cnt
    FROM (
    SELECT *
    FROM r_atpanel_log
    WHERE pt = ‘20190610’
    AND pagetype = ‘normal’
    ) subq
    GROUP BY mid, url
    ) subq2
    WHERE cnt > 100
    ORDER BY cnt DESC
    LIMIT 15;

    可以看出,我们先过滤掉无关的内容,再进行排序,这样子快很多。

    总结:学以致用,一起成长。
    加粗样式

    展开全文
  • 1 什么是数据倾斜数据倾斜即指在大数据计算任务中某个处理任务的进程(通常是一个JVM进程)被分配到的任务量过多,导致任务运行时间超长甚至最终失败,进而导致整个大任务超长时间运行或者失败。外...

    1 什么是数据倾斜

    数据倾斜即指在大数据计算任务中某个处理任务的进程(通常是一个JVM进程)被分配到的任务量过多,导致任务运行时间超长甚至最终失败,进而导致整个大任务超长时间运行或者失败。外部表现的话,在HiveSQL任务里看到map或者reduce的进度一直是99%持续数小时没有变化;在SparkSQL里则是某个stage里,正在运行的任务数量长时间是1或者2不变。总之如果任务进度信息一直在输出,但内容长时间没有任何变化的时候,大概率是出现数据倾斜了。有个特例需要注意,有时候大家会看到SparkSQL的任务信息也显示有1到2个任务在运行中,但进度信息不再刷新而表现为假死很久的时候,这通常是在进行最后阶段的文件操作,并不是数据倾斜(虽然这通常意味着小文件问题严重)。

    再细分一下,倾斜可以分为以下四类:

    1)读倾斜。即某个map(HiveSQL)或者task(SparkSQL)在读取数据阶段长期无法完成。这通常是因为文件分块过大或者此分块数据有异常。这种场景出现频率较小。

    2)算倾斜。即在某个需要排序(如开窗函数或者非广播关联时)或者聚合操作的时候,同一个key(通常是一个或者多个字段或者表达式的组合)的处理耗时过长。这通常是最多的情况,情况也较为复杂。

    3)写倾斜。即某个操作需要输出大量的数据,比如超过几亿甚至几十亿行。主要出现在关联后数据膨胀及某些只能由一个task来操作(如limit)的情况。

    4)文件操作倾斜。即数据生成在临时文件夹后,由于数量巨大,重命名和移动的操作非常耗时。这通常发生在动态分区导致小文件的情况。目前在国内和印度区域已经因为我们默认进行小文件合并而不再存在这个情况,新加坡还有(我们在推动解决)。

    2 为什么会有数据倾斜

    大数据计算依赖多种分布式系统,需要将所有的计算任务和数据经过一定的规则分发到集群中各个可用的机器和节点上去执行,最后可能还需要进行汇总到少数节点进行最后的聚合操作,以及数据写到HDFS/S3等分布式存储系统里以永储存。这个过程被设计来应对大多数情况,并不能应对所有的情况。它具有以下几个特点:

    1)业务数据分布规律无法预知。比如系统无法不经过计算而提前知道某个表的某个字段的取值分布是否大致均匀。

    2)计算结果数量无法预知。比如两表关联的结果对于某些key(关联的一个字段或者多个字段组合)的输出行数无法不经过计算而预知进而针对性处理;又比如对某个字段的值进行split操作或者explode等操作后产生的结果数量无法预知而进行针对性的应对。

    3)某些操作只能由单一节点进行。一切需要维护一个全局状态的大多数操作,如排序,Limit,count distinct,全局聚合等,一般会安排到一个节点来执行。

    上述三个主要特点导致单节点处理的数据量有概率出现巨量,造成了所谓的倾斜问题。当然,这些困难并不是不可解决的。随着时间的推移,越来越多的针对性的优化措施已逐渐出现,也许在不久的将来业务同学不会再被倾斜问题烦恼。

    3 解决案例

    由于未来在OPPO主推SparkSQL,因此以下案例将主要以SparkSQL的角度来展示。

    3.1 事实表关联事实表数据膨胀

    最近有两个业务同学提出一个比较麻烦的问题,就是事实表关联事实表,其中有若干个key的输出达数十亿行,数据膨胀严重,造成数据计算和输出的倾斜。

    比如以下场景:

    c0b382b9d09824ad8fd448cfcfa6e448.png

    我们统计了两个表的倾斜KEY值分布:

    a表:

    49003f647991be4e934a2ea06fcfc829.png

    b表:

    591539b33c8735444185a510d2fdc347.png

    大家可以看出,

    只看option_id=7的关联结果最后是

    46839*130836=6128227404,即61亿行;

    option_id=2的关联结果是

    71080*125541=8923454280,即89亿行。

    属于严重倾斜的情况。

    这种事实表关联事实表的情况在非报表类的计算任务偶尔会遇到。平时我们解决数据倾斜主要是计算结果的过程涉及太多数据要处理导致慢,但通常输出的行数可能并不多,不存在写的困难,所以类似过滤异常数据或者广播关联等方法都不起作用。

    这个问题的本质是一个task最多由一个进程来执行,而相同的key也必须在同一个task中处理,因此在无法改变这个机制的前提下,我们只有想办法减少一个task输出的行数。

    那如何在不影响最终结果的前提下,减少单个task所需要处理数据行数呢?

    其实网上也有许多建议,都是单独处理倾斜的key,通过加前缀后缀等方式打散key,再最后合并处理,但这样做法太麻烦了,不够优雅。我们要追求对业务同学更友好,代码更优雅的方式。

    最后我寻遍所有可用的系统函数,发现了collect_set/collect_list这个聚合函数,可以在保证数据关系不丢失的前提下将数据收拢减少行数。比如以下两行:

    6ff7139307b2f6a0943bc2b1bc588ea3.png

    可以收拢成一行:

    8bc42e4060c0af23c561c08ba1ecce8c.png

    最后我们通过explode+lateral view的方式,可以实现一行展开为多行,从而还原成用户最后期望的明细结果方式。

    上述办法的核心是将原来倾斜的操作(同一个key关联),修改为不再相互依赖的操作(一行变多行)。

    最终代码如下:

    331ab156d0b22aa49e6aaec54fa5195b.png

    注意以上代码里值得注意的地方:

    •代码里的hint(repartition(1000))的作用是考虑到经过collect_list聚合后的数据单行携带的数据经过一行变多行的展开操作后会膨胀很多倍,因此单个任务处理的数据量必须很小,才能保证处理速度够快。这个hint的作用是告诉系统将上一阶段关联后的结果分成1000份,交给下游处理;

    •group by语句里的ceil(rand()*N)作用是将一个key分成最多N行,这样可以限制最后按key关联后生成的行数的上限;

    •通过spark.sql.files.maxPartitionBytes参数控制单个任务处理的数据量,进一步拆分单个任务需要处理的数据。事实上如果第1点里文件足够小,这个参数可以省略。

    经过验证,20分钟任务就完成了,生成了近800亿行的数据,其中包括了19个超十亿行的key。

    3.2 避免排序

    有一些算法基础的同学都知道排序操作在软件领域是开销非常大的操作,目前大规模应用的几大排序算法的时间复杂度中最好的也是O(nlogn),即随着数据量的增长而非线性的增长。这就是说,大规模数据量的排序往往意味着巨大的时间消耗。然而这在大数据SQL中却是常见的情况,从而引发倾斜。一旦有了排序的需求,什么优化参数都不好使了, 一般来说只有进行改写代码。幸运的是,在绝大多数大数据场景下,排序是不必要的,很多时候只是业务同学不解排序在大数据场景下的开销很大而信手写下了排序代码。下面介绍2个改写代码从而避免排序的案例。

    1)用max函数替换排序。

    最近收到一个同事的业务需求,需要对某个业务的埋点数据做一次样本展示,要在约1200亿行数据中,捞出约1万条数据。很简单的一个SQL如下:

    9a85eb686ee66288d6cf3eede734ed77.png

    稍微解释一下SQL的意思:希望取出上报数据里针对某个维度组合的一条内容较为丰富的样本数据,因此以某字段的size作为降序排序并取结果的第一条。

    这个SQL当然跑失败了。我对partition by的字段集合(后续简称key)进行了统计,最大的key有137亿行,另外还有至少10个key的数据量超过20亿行。这样executor的内存加得再大都无法跑成功了。

    这个问题的本质还是对大数据做了不必要的排序(大数据架构里对排序暂无非常高效的处理办法)。因此优化的思路还是想办法减少这种不必要排序。

    既然用户只需要排序后的最大的一条,本质上不就是取某个key的最大值嘛。取出这个最大值,最后再跟源表进行关联,就可以取出最大值对应的那一条数据。

    这里有个前提条件,要想在第二步关联回源表数据的时候干掉排序,我们只有走一条路:广播关联(如果走sort-meger关联,还是会避免不了sort步骤)。这就要求我们的小表(key-最大值)要足够小。通常这个条件都会满足的,因为如果不满足的话,说明key值非常多,非常稀疏,也不会产生倾斜的困境了。如开始就说明了,最后Key的去重数据量不到1万条,完全可以走广播关联。

    最后的代码如下:

    de5dd891099da06d88b89f9c1bc18c0c.png

    注意上述SQL有两点说明:

    •我们使用了semi join,这在日常代码中比较少见。它的意思是,左表去匹配右表,如果一旦发现左表的某条数据的关联key在右表,便保留此条左表的数据,不再继续在右表里查找了。这样做有两个结果:1)速度更快;2)不会把右表的数据放到结果里)。它等价于 select * from left_table where key in (select key from right_table)。但大数据发展过程中一度不支持in的用法(现在部分支持了),因此有这种语法,从效率上看,一般认为这样更高效。

    •因为能匹配到最大值的数据可能有许多条,所以对最后结果再做一次row_number的开窗并取其中一条即可。这个时候由于size(xxxx)的值都是一样的,因此任意取一条均符合业务需求。

    在一般情况下,上述SQL能较好的运行。但我们这次情况出了点意外:经过上述操作后,我们得到的数据还有800多亿行。因为max(size(xxxx) = size(xxxx)的数据占了绝大多数,导致我们匹配回去无法有效的筛选出少量结果。我们必须找到一个能有效区分各行数据的字段,这个字段的值必须很松散。最后我发现比较好的是userid。因此将 max(size(xxxx))替换成了 max(userid),任务很快就跑完了。因为不影响我们讲述优化的原理,所以不再描述这部分细节。

    2)用分位函数替换排序。

    在一个画像任务相关跑得很慢时,业务同学求助于我们,发现慢的代码如下:

    9713d1819ff9c1b321ee4360532b0c28.png

    问题点:上面的代码是想做一个全局排序,然后使用其序号所在位置来进行分类打标。上述代码在排序数据小于5亿5千万行的情况下勉强能运行出结果。但在某一天数据量到了5亿5千万行后就跑不出来,加了reducer的内存到10G也不行。

    8f96a5cf20a3ac4af00ec9a5af928380.png

    新思路:虽然可能还有一些参数能调整,但我认为这不是正确的方向,于是停止了研究,把方向转为干掉全局排序。在和一位前辈沟通的时候,突然意识到,既然业务是想做一个分档,本质上就并不需要具体的排序号,所以理论上完全的排序是可以省掉的。于是自然想到了分位数函数,立马想到了新方案。分位函数计算出数据必须大于或者等于某个值才能处于整个数据排序的某个位置。详情请大家自行搜索。

    改之后代码如下:

    8592ec8feae88bd148034cbc820d7f85.png

    注意上述代码有个小技巧,即与只有一行的子查询结果进行笛卡尔积关联,从而变相的实现了引入p2到p8等4个变量的效果,还算实用。

    效果:对比了新旧算法的结果,差异极小,也在预期范围内。

    0efb2bb19d1e13efeb2c803165fe37eb.png

    再对比了任务执行时间,约有87%的降幅:

    983a100187030d510c439553abdc5758.png

    这个案例的本质在于识别出了费尽资源计算的全局序号是完全不必要的。类似的情况在我们的业务代码里还存在很多,只是目前尚在业务可接受的范围内,存在非常大的优化空间。希望未来能开展专项,以节省计算时间和资源。

    3)通过广播关联彻底避免排序。

    SparkSQL目前处理关联(join)的方法主要有两种:

    a) 广播关联。小表(通过参数spark.sql.au

    toBroadcastJoinThreshold控制,目前我们的默认值是20M)的话会采用广播关联,即将小表的全部数据传输到各节点的内存中,通过直接的内存操作快速完成关联。这种方式最大的好处是避免了对主表的数据进行shuffle,但会增加任务使用的内存量。另外特别说明3点:

    •目前我们的sparksql优化器尚不能非常准确地判断一个子查询结果(也被当成一张小表)是否适合进行广播,因此还在跟进解决中;

    •左表无论大小都不能被广播;

    •某些情况下会有类似:Kryo serialization failed: Buffer overflow 这样的OOM出现,并 “To avoid this, increase spark.kryose

    rializer.buffer.max value”。但其实这样设置会无效。实质原因是:虽然某张表小于32M,但由于高度压缩后,解压结果的行数达到了数千万,造成了节点的OOM。这个时候,只能手动禁掉广播关联。

    b) Sort-Merge关联。即先将两表按连接字段进行排序,然后在些基础上进行匹配关联。由于数据是排序过的,只需要一次性的匹配即可完成最终的关联,速度较快。但这种方法的弊端是要进行对关联key的排序,并且每个相同的Key和对应的数据必须分配到一个executor里,引发大量的shuffle操作;另一方面如果一个executor需要处理一个巨量的key,通常会花费大量的时间以及大量的磁盘IO。

    通过上述原理描述可以看出如果采用广播关联,引擎完全不用做任何排序,自然也不会有排序带来的倾斜了,这是效率巨大的提升,当然代价就是会增加内存占用。一般来说这种内存使用的增加被认为是划算的。

    如果引擎没有识别出来,我们可以通过主动指示的办法影响执行计划。比如以下:

    1adba819d874cbf851387efd6226aedd.png

    要让执行计划改成广播s子查询结果,加hint mapjoin (也可以是 broadcast)就可以了。

    5711c5381d78d659d3549b5001ee0941.png

    从实际的结果看,广播关联的提速都有翻倍以上的效果。

    3.3 写倾斜的避免

    这部分简要描述一下。在动态分区场景下,我们常常很难预料最后每个分区将要输出的数据量会是多少,但分配的task数量对于每个最终分区都是固定的。以国家分区条件为例,印尼这个分区如果是输出10亿行,而新加坡只输出100万行,这个时候如果我们只分配2个任务去写数据,印尼这个分区单个任务会承受1亿行的任务,会非常慢。而如果设置为100个任务来写数据,对印尼这个分区来说是比较合适的,但新加坡这个分区分产生100个小文件,对后续的文件操作和未来下游任务的读取都有消极的影响。最后经过实践后,找到一个比较好的办法。即找出倾斜的分区key,通过distribute by + case when表达式,让引擎对不同的分区做不同数量的数据分发。具体代码(以region为动态分区字段):

    960f68cb267237ae679375712e83ce17.png

    目前这种情况在海外任务上还需要应用,未来随着我们推动AWS解决小文件自动合并问题,应该不用再操心了。

    3.4 非法值过滤

    这应该是网上讲得比较多的办法,我也简略说下。

    在优化战略生态部门的任务dwd_ocloud_da

    u_info_d任务的时候,我们发现任务的运行时间一直在增长,一度达到7个小时,直到8月1号便再也跑不成功,总是OOM(内存不够),即使将executor的内存调高到10G依然解决不了问题。经过仔细诊断,发现任务慢在一个开窗函数阶段,代码如下:

    69fc22552e36e20a2178f8750af15a63.png

    在对guid这个key进行初步统计后,发现为空值的数量竟然有数亿行,并不断增长:

    78caf935954a355f740b58a3579a42e2.png

    这也就解释了运行时长不断增长,排序的内存开销和时长都不断增长。经过和业务同学的沟通,确认空值无意义,进行排除:

    fabe0097fca9dd7504cc59540b77f167.png

    然后在默认的参数下进行了重跑,30分钟内就跑完了。耗时下降约90%,效果明显。

    24a5115c554d6b432d1201fec0067763.png

    这个例子里,倾斜值恰好是无效的可以直接过滤,比较幸运。那同学们会问,如果倾斜值是有价值的怎么办?通常来说是需要将这类倾斜值单独拎出来以另外一套针对性的逻辑来计算,然后将结果union all回到其他非倾斜的数据计算结果里。

    4 结语

    数据倾斜处理的情况基本上局限在上述案例分类里,相信大家稍加学习都能掌握。未来我们有计划开发诊断和优化的工具,重点帮大家找出倾斜的节点和提出代码级别的优化建议。敬请期待!

    作者简介

    Luckyfish  OPPO大数据服务质量负责人

    主要负责大数据平台支持维护及服务质量保证工作,曾供职于京东科技,有较丰富的大数据任务开发和性能优化经验,同时对产品体验和成本优化有较多兴趣和经验。

    展开全文
  • 随着现在传媒技术的地不断发展,摄影成为越来越来重要的一种技术,但是有人是否听说过倾斜摄影呢,下面就开始深入讲解一下,倾斜摄影技术近些年发展起来的一项高新技术,它颠覆了以往正射影像只能从垂直角度拍摄的...

    随着现在传媒技术的地不断发展,摄影成为越来越来重要的一种技术,但是有人是否听说过倾斜摄影呢,下面就开始深入讲解一下,倾斜摄影技术近些年发展起来的一项高新技术,它颠覆了以往正射影像只能从垂直角度拍摄的局限,通过在同一飞行平台上搭载多台传感器,同时从一个垂直、四个倾斜等五个不同的角度采集影像,将用户引入了符合人眼视觉的真实直观世界。

    倾斜摄影技术特点

    倾斜摄影是在摄影测量技术发展和人们需求增加的基础上发展起来的。传统的竖直摄影只能获取地物顶部信息,对于地物侧面信息则无法获得;倾斜影像能让用户从多个角度观察被制作建筑,更加真实地反映地物的实际情况,极大地弥补了基于正射影像分析应用的不足。

    通过配套软件的应用,可直接利用成果影像进行包括高度、长度、面积、角度、坡度等属性的量测,扩展了倾斜摄影技术在行业中的应用;针对各种三维数字城市应用,利用航空摄影大规模成图的特点,加上从倾斜影像批量提取及贴纹理的方式,能够有效地降低城市三 维建模成本。

    倾斜摄影与竖直摄影基本原理相同,但其与竖直摄影相比仍面临不少难题,如:建筑物在倾斜影像中几何变形、数据遮挡、数据冗余、影响匹配以及多视角影像联合平差等。

    技术创新 为了降低倾斜影像的获取成本和周期,国内在引进和开发基于有人机的倾斜航摄仪的同时,同步开展了适宜在无人机、动力三角翼、直升机上进行搭载的轻量化、微型化倾斜航摄仪的研发工作。

    常规的实景三维建模主要包括多视影像同名像点匹配、区域网联合平差、密集点云生成、三角网构建、纹理映射以及建立多细节层次结构等数据处理步骤。然而,为了保证实景三维模型最佳的视觉效果,技术人员针对各类传感器所获取的倾斜影像数据特性,开发了多视影像预处理(云雾处理、色调一致性调整等)、三维模型优化编辑(水面漏洞修复、建筑结构修复)等相关系统软件,有效地提高了三维模型的质量可靠性。

    倾斜摄影建模技术的优势

    传统三维建模通常使用3dsMax、AutoCAD等建模软件,基于影像数据、CAD平面图或者拍摄图片估算建筑物轮廓与高度等信息进行人工建模。这种方式制作出的模型数据精度较低,纹理与实际效果偏差较大,并且生产过程需要大量的人工参与;同时数据制作周期较长,造成数据的时效性较低,因而无法真正满足用户需要。

    倾斜摄影测量技术以大范围、高精度、高清晰的方式全面感知复杂场景,通过高效的数据采集设备及专业的数据处理流程生成的数据成果直观反映地物的外观、位置、高度等属性,为真实效果和测绘级精度提供保证。同时有效提升模型的生产效率,采用人工建模方式一两年才能完成的一个中小城市建模工作,通过倾斜摄影建模方式只需要三至五个月时间即可完成,大大降低了三维模型数据采集的经济代价和时间代价。目前,国内外已广泛开展倾斜摄影测量技术的应用,倾斜摄影建模数据也逐渐成为城市空间数据框架的重要内容。

    倾斜摄影建模完成后,如何在Web端进行发布展示一键分享?

    Wish3D·Earth平台是图新地球技术团队基于 WebGL技术自主研发的国产实景三维模型Web端发布展示平台,支持发布大规模(TB级)各类二三维数据,包括卫星影像、地形、倾斜模型、人工模型、BIM模型等,真实还原了实景三维模型和人工模型同场景展示效果,同时能够支持数据发布后一键分享到网页端、手机端进行成果汇报展示。

     

    展开全文
  • 经济学原理中需求曲线为什么向右下方倾斜的详细解释
  • 细节增强的matlab代码
  • 校正倾斜的文本

    千次阅读 2020-12-08 13:43:06
    有时候文本是倾斜的,则不利于文本识别,如下图所示,那么进行文本识别之前我们需要应用文本倾斜校正算法(text skew correction,deskewing text)。对于一幅包含旋转文本块的图像,我们需要通过以下方式纠正文本倾斜...
  • 最近产品有一个需求是:要在一个距形卡片上做一个倾斜的Tag,类似: (PS:不要注意那两毛三分的穷鬼),刚开始想着用UI切图就可以了嘛,but是不可以的,在不同手机上分辨率是不同的,直接用图片适配肯定会有问题,...
  • FLINK数据倾斜的解决思路

    千次阅读 2021-10-09 16:09:40
    排查思路 1、查看该任务是否有反压现象 利用Flink WebUi查看任务是否有反压情况,结果正常,没有出现反压现象。 如果有反压,一般是红色节点往后的一个节点效率或者处理...这种情况出现数据倾斜,是由于 按照字段 keyB
  • 我在解释它的工作方面做得很糟糕。 考虑一下iOS 7和8; 当您将手机向侧面倾斜时,背景图片会如何移动一点。 使用jQuery和一些crabby localStorage(以存储设备的原始位置)。 在页面加载时使用localStorage,存储...
  • Echarts x轴字体倾斜

    2021-04-16 02:33:29
    如图: 在这里插入图片描述 稍微解释一下 interval 坐标轴刻度标签的显示间隔(在类目轴中有效哦),默认会采用标签不重叠的方式显示标签(也就是默认会将部分文字显示不全) 可以设置为0强制显示所有标签,如果设置为...
  • 主要分为map端倾斜和reduce端倾斜,map端倾斜主要是因为输入文件大小不均匀导致,reduce端主要是partition不均匀导致. 在hive中遇到数据倾 ... Hadoop数据倾斜及解决办法 数据倾斜:就是大量的相同key被partition分配到...
  • 听老人家说:多看美女会长寿 ...下面献上完整代码,代码重要位置会做相应解释 <html lang="en"> <head> <meta charset="UTF-8"/> <script src="Build/CesiumUnminified/Cesiu
  • 通过相关的理论和试验对比研究了圆球倾斜入水冲击压力的性质,解释了冲击压力的振荡现象。试验以一个直径15.24 cm的圆球为对象,设计了控制球体倾斜入水的“单摆”装置,同步记录了圆球入水初期的流场状态和表面压力。...
  • 1172. 二叉树倾斜程度

    2021-06-07 15:39:45
    1172.二叉树倾斜程度 给定一个二叉树,返回整棵树的倾斜程度。...解释: 1 / \ 2 3 节点2的倾斜程度 : 0 节点3的倾斜程度 : 0 节点1的倾斜程度 : |2-3| = 1 整棵树的倾斜程度 : 0 + 0 + 1 = 1 *...
  • 在许多光学系统中,元件故意从光轴倾斜或偏心。本文介绍如何在序列模式下对这些类型的系统进行建模。联系工作人员获取附件本文介绍了插入坐标断裂曲面以允许光学元件的偏心和倾斜的过程。第一部分介绍坐标断点曲面的...
  • 解释: 节点 2 的倾斜度:0 节点 3 的倾斜度:0 节点 1 的倾斜度:|2-3| = 1 二叉树的倾斜度:0 + 0 + 1 = 1 笔记: 任何子树中节点值的总和都不会超过 32 位整数的范围。 所有倾斜值都不会超过 32 位整数的范围。
  • 倾斜摄影数据的普及伴随着...SuperMapiDesktop提供了许可可以进行倾斜摄影优化的手段,我们可以针对自己的数据情况选取不同的优化手段,下面我会针对几种常见的情况来一一进行详细的解释,并且给出优化的步骤。 ...
  • 如何监控倾斜1、监控数据库级别倾斜2、监控表级倾斜出现数据倾斜的原因和解决办法1.分布键选择不正确,导致数据存储分布不均。例如选择的字段某些值特别多,由于数据是按分布键VALUE的HASH进行分布的,...
  • Hadoop数据倾斜问题

    2021-03-16 16:45:11
    数据倾斜:大量的key被partition分配到一个分区里,mapreduce程序执行时,导致承担大量key的reduce节点运行慢,而由于木桶效应,整个程序的处理时间取决于最后的reduce节点,这就是数据倾斜。直观解释就是:忙的忙死...
  • Hive 执行 MapReduce 过程中经常会出现数据倾斜问题,具体表现为:作业经常在 Reduce 过程完成 99% 的时候一直停留,最后 1% 一直保持很久才完成。这种情况是由于:在数据量很大的情况下,在 MapReduce 的 Shuffle ...
  • HTML5 :b/strong加粗,i/em倾斜区别

    千次阅读 2021-06-12 19:14:29
    解释1i倾斜,h4:无意义的斜体,不推荐,h5:分类名称,技术术语,外语中的谚语,想法,无意义的排版em倾斜,h4:一般强调(倾斜文本)h5:句子中强调b加粗,h4:无意义的加粗:不推荐,h5:文档概要中的关键字,评论中...
  • 通过实验研究发现,煤岩组合试样中煤岩比例不同,煤岩组合试样的单轴抗压强度也相应不同,可以运用煤岩组合试验结果解释倾斜煤层两帮应力随煤厚变化的关系。数值模拟结果和现场微震监测结果均证明了煤层厚度对于倾斜...
  • 听老人家说:多看美女会长寿 ...下面献上完整代码,代码重要位置会做相应解释 <html lang="en"> <head> <meta charset="UTF-8"/> <script src="Build/CesiumUnminified/Cesiu
  • 地图之家:cesium+leaflet+echart+地图数据+地图工具等相关内容的介绍文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信...效果如下所示:下面献上完整代码,代码重要位置会做相应解释 完整代码包下载......
  • 地图之家:cesium+leaflet+echart+地图数据+地图工具等相关内容的介绍文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。...效果如下所示:下面献上完整代码,代码重要位置会做相应解释.........
  • cesium接入加载倾斜摄影(cesium篇.16)

    千次阅读 多人点赞 2021-07-07 14:35:56
    地图之家欢迎您的订阅 后续会不断围绕着2D、3D地图技术丰富该专栏内容 ...文章末尾处提供保证可运行...下面献上完整代码,代码重要位置会做相应解释 <html lang="en"> <head> <meta charset="UTF-8"/&g

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,519
精华内容 9,407
热门标签
关键字:

倾斜的解释