栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 前沿技术 > 大数据 > 大数据系统

sql数据处理的长尾问题及优化

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
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 
        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切分成热点数据和非热点数据两部分分别处理,最后合并。

  1. JOIN Key存在很多空值导致长尾:此时可以将空值处理成随机值。因为空值无法关联上,只是分发到了一处,因此给予随机值既不会影响关联也能避免聚集。

假设a表的id存在很多空值,那么我们在关联的时候可以将关联条件转化。见下:

on a.id = b.id
--转化为
on coalesce(a.id,rand()*9999) = b.id
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/280109.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号