`
猫耳呀
  • 浏览: 165421 次
社区版块
存档分类
最新评论

MaxCompute JOIN优化小结

阅读更多
摘要: Join是MaxCompute中最基本的语法,但由于数据量和倾斜问题,非常容易出现性能问题。一般情况下,join产生的问题有两大类: 数据倾斜问题:join会将key相同的数据分发到同一个instance上处理,如果某个key上的数据量特别多则会导致该instance处理时间比其他instance...

原文地址:http://click.aliyun.com/m/43804/

Join是MaxCompute中最基本的语法,但由于数据量和倾斜问题,非常容易出现性能问题。一般情况下,join产生的问题有两大类:
  ● 数据倾斜问题:join会将key相同的数据分发到同一个instance上处理,如果某个key上的数据量特别多则会导致该instance处理时间比其他instance处理时间长,这就是我们常说的数据倾斜,这也是join计算性能问题的罪魁祸首;
  ● 数据量问题:关联的两表基本没有热点问题,但两个表数据量都非常大同样会影响性能,比如记录数达几十亿条,如商品表、库存表等;
      
虽然MaxCompute中提供了一些通用的优化算法,但从业务角度解决性能问题往往更精确,更有效。对于MaxCompute sql优化,在云栖社区上已经有比较多的经验积累,本文主要对join产生的性能问题以及解法做些总结。

不同数据类型key关联

例子

       浏览IPV日志以商品id关联商品表,假设日志表的商品id字段是string类型,商品表中的商品id是bigint类型,那么在关联中,关联key会全部转换成double类型进行比较,设想由于埋点问题日志表中的商品id存在很多非数值的脏数据,那么转换成double后值都变为NULL或者截取前面的数值,关联时就会产生数据倾斜问题,更严重的会造成数据错误。

解法

      关联时手工进行数据格式转换,在这种情况下一般将bigint类型key转换成string类型。
select a.*
from ipv_log_table a
left outer join item_table b
on a.item_id = cast(b.item_id as string)
      
思考下,假如反过来将string类型转换成bigint、假如IPV日志表中的商品id大部分为无效值(比如0)、又假如IPV日志表中没有无效值但是有热点key会有什么问题呢?下面的例子会解答这些问题。

小表join大表

         Join中存在小表,一般这个小表在100M以内,可以用mapjoin,避免分发引起的长尾。拿上面的例子来说,假如商品表数据量只有几万条记录(这里只是打个比方,现实业务中商品表一般都是非常庞大的),但是IPV日志表中的商品id 80%值为0的无效值,且记录数有几十亿,如果采用上述SQL写法,数据倾斜是显而易见的,但利用mapjoin可以有效解决这个问题:
select /*+ MAPJOIN(b) */a.*
from ipv_log_table a
left outer join item_table b
on a.item_id = cast(b.item_id as string)

mapjoin原理 
    
       把小表广播传递到所有的Join Task Instance上面,然后直接和大表做Hash Join,简单的说就是将join操作提前到map端,而非reduce端。

mapjoin使用注意点
  ● 小表在left outer join 时只能是右表, right outer join 时只能是左表, inner join 时无限制,full outer join不支持mapjoin;
  ●  mapjoin最多只支持8张小表,否则会报语法错误;
  ● mapjoin所有小表内存限制不能超过2GB,默认为512M;
  ● mapjoin支持小表为子查询;
  ● mapjoin支持不等值连接或者使用or连接多个条件;

大表join大表存在无效值
   
   在小表join大表时我们已经了解到通过mapjoin将小表全部加载到map端可以解决倾斜问题,但假如‘小表‘不够小,mapjoin失效的时候该怎么办呢?同样以本文第一个场景为例,IPV日志表中80%商品id都为无效值0(目前MaxCompute底层已经针对NULL值进行优化,已经不存在倾斜问题了),这时关联十几亿量级商品表那就是个灾难。

解法1-分而治之:
      
我们可以事先知道无效值是不可能关联出结果的,而且完全不需要参与关联,所以可以将无效值与有效值数据分开处理:

select a.visitor_id
      ,b.seller_id
from (
      select
      from ipv_log_table
      where item_id > 0
) a
left outer join item_table b
on a.item_id = b.item_id

union all

select a.visitor_id
      ,cast(null as bigint) seller_id
from ipv_log_table
where item_id = 0

解法2-随机值打散:
      
我们也可以以随机值代替NULL值作为join的key,这样就从原来一个reduce来处理倾斜数据变成多reduce并行处理,因为无效值不参与关联,即使分发到不同reduce,也不会影响最终计算结果:

select a.visitor_id
      ,b.seller_id
from ipv_log_table a
left outer join item_table b
on if(a.item_id > 0, cast(a.item_id as string), concat('rand',cast(rand() as string))) = cast(b.item_id as string)

解法3-转化为mapjoin:

      虽然商品表有十几亿条记录,不能直接通过mapjoin来处理,但在实际业务中,我们知道一天内用户访问的商品数是有限的,在业务中尤为明显,基于此我们可以通过一些处理转换成
mapjoin:

select /*+ MAPJOIN(b) */
       a.visitor_id
      ,b.seller_id
from ipv_log_table a
left outer join (
   select /*+ MAPJOIN(log) */
         itm.seller_id
        ,itm.item_id
   from (
         select item_id
         from ipv_log_table
         where item_id > 0
         group by item_id
   ) log join item_table itm
   on log.item_id = itm.item_id
) b
on a.item_id = b.item_id

解法对比

       解法1和解法2是通用解决方案,对于解法1,日志表被读取两次,而解法2中只需读取一次,另外任务数解法2也是少于解法1的,所以总的来看解法2是优于解法1的。解法3是基于一定的假设,随着业务发展或者某些特殊情况下假设可能失效(比如一些爬虫日志,可造成访问商品数接近全量),这会导致mapjoin失效,所以在使用过程中要根据具体情况来评估。

一个古老的例子

       最后要讲一个古老的优化case,虽然历史比较久远,目前已没有相关问题,但优化思路值得借鉴。情况是这样的,历史上并存过两套商品维表,一份主键是字符串id,新的商品表也就是目前在使用的主键是数字id,字符串id和数字id做了映射,存在商品表中的两个字段中,所以在使用中需要分别过滤数字id、字符串id然后分别和商品表关联,最后union起来得到最终结果。
      思考下如果换成下面的优化思路是不是更优呢?

select ...
from ipv_log_table a
join (
      select auction_id as auction_id
      from auctions
      union all
      select auction_string_id as auction_id
      from auctions
      where auction_string_id is not null
) b
on a.auction_id = b.auction_id


答案是肯定的,可以看到优化后商品表读取从2次降为1次,IPV日志表同样,另外MR作业数也从2个变为1个。

总结

       对于MaxCompute sql优化最有效的方式是从业务的角度切入,并能够将MaxCompute sql转化为mapreduce程序来解读。本文针对join中各种场景优化都做了一些梳理,现实情况很可能是上述多场景的组合,这时候就需要灵活运用相应的优化方法,举一反三。

识别以下二维码,阅读更多干货

分享到:
评论

相关推荐

    万台集群性能优化方法——MaxCompute性能优化实践.zip

    万台集群性能优化方法是MaxCompute在处理大规模数据时面临的重要课题,旨在提高计算效率,降低资源消耗,确保服务的稳定性和响应速度。下面我们将深入探讨MaxCompute性能优化的实践策略。 一、SQL查询优化 1. 精简...

    MaxCompute索引优化实践分享.pdf

    此外,文档还讨论了MaxCompute2.0在Join操作上的优化。Join操作是数据库查询中常见的场景,尤其是在复杂的数据分析查询中。通过适当的索引优化,可以减少Join操作的计算量,从而提升查询效率。文中给出了TPC-H Q4的...

    Left join优化规则的研究

    【Left Join 优化规则的研究】 在数据库查询优化中,Left Join 的处理是至关重要的,因为它涉及到数据的完整性和性能效率。对于应用开发人员而言,理解 Left Join 的优化规则能够提高查询效率,尤其是在某些数据库...

    MaxCompute基于代价的优化器平台.pptx

    MaxCompute的优化引擎还考虑了分布式查询的特定挑战,如分区、广播JOIN等,以及如何优化用户自定义函数(UDF)。UDF的优化是个关键问题,因为它们可能影响数据的处理方式和分布。MaxCompute通过理解UDF的特性,如...

    MySQL中Nested-Loop Join算法小结

    此外,优化JOIN还包括创建合适的索引,特别是在JOIN列上,以及避免全表扫描,确保JOIN操作尽可能高效。 总的来说,理解MySQL中的Nested-Loop Join机制对于数据库性能优化至关重要。通过深入理解NLJ的工作原理、变形...

    mysql Join使用以及优化

    MySQL数据库中Join操作的使用及优化是一项重要的技能,它涉及到数据库中表与表之间的关联查询。在执行Join操作时,数据库管理系统需要按照某种算法将多个表中的数据记录联合起来,并返回查询结果。Join操作的主要...

    MaxCompute计算长尾问题优化.zip

    本资料“MaxCompute计算长尾问题优化.zip”主要探讨如何针对这一问题进行优化,提升系统的整体性能。 1. **理解计算长尾问题**:计算长尾问题是指在分布式计算环境中,由于数据分布不均、计算任务复杂度差异等原因...

    SQL语句优化之JOIN和LEFT JOIN 和 RIGHT JOIN语句的优化

    6. 调整JOIN顺序:根据表的大小和JOIN条件,调整JOIN顺序,使小表优先。 7. 考虑临时表:对于复杂的JOIN,考虑将中间结果存入临时表,降低复杂度。 总之,理解JOIN的工作原理,合理选择JOIN类型,优化JOIN顺序,...

    面向Flink的多表连接计算性能优化算法

    Semi Join算法则是针对星型连接的优化算法,旨在减少需要shuffle的数据量。该算法可以大大减少需要shuffle的数据量,减少网络IO代价,提高了Flink多表连接的性能。 在TPC-H数据集上的实验结果表明,提出的算法可以...

    藏经阁-MaxComputeSQL2.0全新的计算引擎.pdf

    MaxCompute 2.0提供了多种优化规则,包括基础优化规则、裁剪列、分区裁剪、子查询裁剪、谓词下推、合并谓词、折叠常量、谓词推导探测等。这些规则可以根据实际情况选择合适的优化策略,提高查询性能。 Join重排 ...

    oracle性能优化技巧

    ### Oracle性能优化技巧详解 #### 一、Oracle优化器模式 在Oracle数据库中,优化器是决定查询执行计划的关键组件,其目标是最小化资源消耗并最大化查询性能。Oracle提供了三种主要的优化器模式:基于规则(RULE)...

    SQL left join

    SQL Left Join SQLLeft Join是一种常用的数据库查询操作,它可以将两个或多个表格中的数据结合起来,以便更好地分析和处理数据。在本文中,我们将详细介绍SQL Left Join的使用方法、特点和区别,以及与Right Join...

    inner join、 left join 、right join、 outer join之间的区别

    ### inner join、left join、right join、outer join之间的区别 在数据库操作中,连接(Join)是一种非常重要的操作,用于组合两个或多个表中的数据。根据连接的方式不同,可以分为几种类型:`INNER JOIN`、`LEFT ...

    PLSQL优化规则小结

    标题:“PLSQL优化规则小结” 描述:本文总结了PL/SQL优化的若干规则,旨在提升数据库查询效率,是作者实践经验的提炼。 知识点详述: ### 1. 避免对索引列进行计算 - **原规则**:尽量避免在WHERE子句中对索引...

    阿里大数据计算服务MaxCompute-计量计费.pdf

    SQL复杂度由SQL语句中的关键字数量决定,例如Join、Group By、Order By等,不同数量级的关键字对应不同的复杂度系数。费用计算公式为:一次SQL计算费用 = 计算输入数据量 * SQL复杂度 * SQL价格。账单会在计算任务...

    转--一次HASH JOIN 临时表空间不足的分析和优化思路

    1. **查询优化**:检查SQL语句,尝试使用其他类型的JOIN,如Nested Loop JOIN或Merge JOIN,它们可能对内存需求较小。同时,考虑是否可以通过添加索引、减少JOIN条件或使用子查询来降低数据量。 2. **内存调整**:...

    MaxCompute大数据运算挑战与实践.pdf

    针对分布式场景,MaxCompute还特别设计了多种优化策略,如Pair-wise Join、Broadcast Join等,以及基于历史数据的优化(HBO),以提升查询性能。 在分布式调度上,MaxCompute面临诸多挑战,如性能、弹性配额、任务...

    藏经阁-MaxCompute 的NewSQL演进之路.pdf

    详细介绍了MaxCompute 2.0的背景、关键技术、NewSQL回归关系型、非结构、半结构和结构化数据的支持、强大的DAG执行图表示、完整的用户自定义函数体系、强大的优化器等。 MaxCompute 2.0背景关键技术 MaxCompute ...

    关于sql的left join,right join,inner join,outerjoin

    例如,使用索引、优化JOIN条件、避免全表扫描等都是提高JOIN查询效率的重要策略。同时,理解数据库系统的特定行为,比如MySQL对FULL OUTER JOIN的支持,也是数据库开发者需要关注的点。 总之,LEFT JOIN、RIGHT ...

    【MapReduce篇06】MapReduce之MapJoin和ReduceJoin1

    小结 MapReduce 之 MapJoin 和 ReduceJoin 是两种常见的 Join 操作,用于连接来自不同数据源的数据。MapJoin 可以减少数据传输量,提高计算效率,而 ReduceJoin 可以处理大量的数据。根据具体的业务需求和数据特点...

Global site tag (gtag.js) - Google Analytics