sql数据处理的长尾问题及优化
长尾问题是分布式计算⾥最常见的问题之⼀。主要原因是因为数据分布不均,导致各个节点的⼯作量不同,整个任务就需要等最慢的节点完成才能完成。
Map长尾
主要原因是某些Map Instance读取的数据量相对于其他的Instance多很多。
优化⽅法:
1. 使⽤统计好的中间层汇总表,减少⼤数据量读取;
2. ⾏裁剪:检查代码读取的数据量是不是⽐⾃⼰的需求多,尽可能限制分区或者使⽤where条件过滤掉不需要的数据;
3. 列裁剪:限制select的字段数据,尽量不⽤select *,列的利⽤率低。⽐如原表有100个字段,如果只⽤了其中1个字段,那么利⽤率
只有1%。对于列数特别多的输⼊表,Map阶段处理只需要其中的某⼏列,可以通过在添加输⼊表时,明确指定输⼊的列,减少输⼊量;
4. 使⽤union all:在所取的数据量很⼤的时候,可以尝试使⽤union all将所取的数据分开查询并集合在⼀起。⽐如要取3个⽉的数据,
则可以分别写三段sql,每段取⼀个⽉的数据,再union all起来。
Reduce长尾
主要原因是分发键分布不均匀,存在热点数据(⽐如按照城市汇总⽤户量时,某⼀个城市的⽤户量占⽐超过60%,就可能出现Reduce长尾)。
优化⽅法:
1. 使⽤统计好的中间层汇总表,这⼀点同Map长尾处理⽅式⼀样。
2. ⾏裁剪/列裁剪:这⼀点也和Map长尾处理⽅式⼀样。
3. 不同的列进⾏count distinct操作,造成map端数据膨胀,优化sql语句, 两次group by分多次处理
⽐如:
SELECT  CITY
,COUNT(DISTINCT USER_ID)AS USER_COUNT
FROM TABLE
GROUP BY CITY
;
如果长尾发⽣,可以考虑减少聚合时的数据量,⽐如可以先对CITY和USER_ID进⾏group by作为⼀个⼦查询,再在外层对CITY进⾏分组计算,具体优化语句为:
SELECT  CITY
,COUNT(USER_ID)AS USER_COUNT
sql语句优化方式FROM(
SELECT  CITY
,USER_ID
FROM TABLE
GROUP BY CITY
,USER_ID
)
GROUP BY CITY
;
Join长尾
JOIN阶段会将JOIN Key相同的数据分发到同⼀个Join Instance上执⾏处理。如果某个Key上的数据量⽐较多,会导致该Instance执⾏时间⽐其他Instance执⾏时间长。该JOIN Task的⼤部分Instance已执⾏完成,但少数⼏个Instance⼀直处于执⾏中,这种现象称之为Join长尾。
主要原因是表关联的键(key)分布不均匀,存在热点(本质就是关联的时候key值出现1对多的情况,这个多的部分就是热点)。
优化⽅法:
1. 进⾏关联之前对数据进⾏去重,或者先对每个表进⾏分组汇总,尽量使⽤主键(唯⼀键)进⾏关联。
2. 两表关联存在热点key:
a、⼤⼩表关联,使⽤Mapjoin,将⼩表加载到内存,直接分发到Map Instance所在机器上,在读取的阶段就做hash-join。值得注意的是Mapjoin的⼩表⼤⼩有限制,⽽且⼩表必须要是从表(即不能是left join的左表,也不能是right join的右表)。
⽐如:假设表a左关联表b,b是⼩表:
SELECT  a.id
,b.name
FROM    a
LEFT OUTER JOIN b
ON      a.id = b.id
;
转化为:
SELECT/*+mapjoin(b)*/
a.id
,b.name
FROM    a
LEFT OUTER JOIN b
ON      a.id = b.id
;
如果⼤⼩表关联,⽽⼩表是主表,此时⽆法使⽤mapjoin,参考如下处理⽅式:
先将⼩表和⼤表利⽤MAP JOIN进⾏inner join,得到⼩表和⼤表的交集中间表,且这个中间表⼀定是不⼤于⼤表的(key倾斜程度与表的膨胀⼤⼩成正⽐)。然后⼩表再和这个中间表进⾏LEFT JOIN,这样操作的效果等于⼩表LEFT JOIN⼤表。
b、关联的两个表都⽐较⼤。
⾸先考虑去重。其次考虑将热点数据分开处理:先将主表热点Key取出,再⽤热点Key切分成热点数据和⾮热点数据两部分分别处理,最后合并。
3. JOIN Key存在很多空值导致长尾:此时可以将空值处理成随机值。因为空值⽆法关联上,只是分发到了⼀处,因此给予随机值既不会
影响关联也能避免聚集。
假设a表的id存在很多空值,那么我们在关联的时候可以将关联条件转化。见下:
on a.id = b.id
--转化为
on coalesce(a.id,rand()*9999)= b.id

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。