2024年10月mapjoin和leftjoin(hive中mapjoin和普通join的区别)

 更新时间:2024-10-12

  ⑴mapjoin和leftjoin(hive中mapjoin和普通join的区别

  ⑵hive中mapjoin和普通join的区别

  ⑶hive支持’leftjoin’写;hiveleftouterjoin:右边行左边表应,每行都映射输;右边没行与左边行应,输左边行,右边表字段NULL;hiveleftsemijoin:相于SQLin语句两测试数据表建表语句...

  ⑷列裁剪和分区裁剪、谓词下推、sortby替换orderby?、groupby代替distinct、groupby配置调整map端预聚合:sethive.map.aggr=true;sethive.groupby.mapaggr.checkinterval=倾斜均衡配置项:sethive.groupby.skewindate=true、join优化.大小表,小表前置.多表Join时key相同.利用mapjoin特性.分桶表mapjoin.倾斜均衡配置项:设置hive.optimize.skewjoin=true,开启后,在join过程中hive会将计数超过阈值hive.skewjoin.key(默认)的倾斜key对应的行临时写进文件中,然后再启动另一个job做mapjoin生成结果。通过hive.skewjoin.mapjoin.map.task参数还可以控制第二个job的mapper数量,默认..优化sql处理join数据倾斜..、空值或无意义的值:若不需要空值数据,就提前写到where语句过滤掉,如果需要保留的话,将空值key用随机方式打散。..、单独处理倾斜key..、不同数据类型,join的关联字段类型不一样,导致耗时长,所以需要注意做类型转换(join关联字段,一个是int,一个是string,,计算key的hash值时默认时int类型做的,这样导致所有真正的string类型的key都分配到一个reducer上了..、mapjoin的小表比较大的时候,,无法直接使用mapjoin,则select/*+mapjoin(b)*/?from?aleftjoin(select/*+mapjoin(b)*/frombinnerjoina).、mapreduce优化..、调整mapper数mapper数量与输入文件的split数息息相关。如果想减少mapper数,就适当提高mapred.min.split.size,split数就减少了;如果想增大mapper数,除了降低maperd.min.split.size之外,也可以提高mapred.map.task;一般来讲,如果输入文件是少量大文件,就减少mapper数;如果是大量非小文件,就增大mapper数,如果是小文件,就喝吧小文件..调整reducer数使用参数mapred.reduce.task可以直接设定reducer数量,如果不设置的话,hive会自行推测,推测逻辑如下:参数hive.exec.reducers.bytes.per.reducer.设定每个reducer能够处理的最大的数据量,默认时G参数hive.exec.reducers.max设定每个job的最大的reducer数量,默认时或者得到reducer数:reducers_num=min(total_input_size/reducers.bytes.per.reducer,reducers.max)reducer数量与输出文件的数量相关,如果reducer数太多,会产生大量小文件,对hdfs造成压力,如果reducer数太少,每个reducer要处理很多数据,容易拖慢运行时间或造成oom..合并小文件输入阶段合并:需要更改hive的输入文件格式,即参数hive.input.format,默认值是.apache.hadoop.hive.ql.io.hiveiputformat,我们该成.apache.hadoop.hive.ql.io.binehiveinputformat.这样比调整mapper数时,又多出两个参数,分别是mapred.min.split.size.per.node和mapred.min.split.size.per.rack,含义是单节点和单机架上的最小split大小。如果发现又split大小小于这两个默认值MB,则会进行合并输出阶段合并:直接将hive.merge.mapfiles和hive.merge.mapredfiles都设置为true即可。hive.merge.mapfiles表示将map-only任务的输出合并hive.merge.mapredfiles表示将map-reduce任务的输出合并另外hive.merge.size.per.task可以指定每个task输出后合并文件大小的期望值hive.merge.size.smallfiles.avgsize可以指定所有输出文件大小的均值阈值,默认时G.启用压缩压缩job的中间结果数据和输出数据,可以少量CPU时间节省出很多空间。压缩方式一般选择snappy,效率最高,要启用中间压缩,需要设定:hive.exec.press.intermediate为true,同时指定压缩方式hive.intermediate.pression.code为.apache.hadoop.io.press.snappycode.另外,参数hive.intermediate.pression.type可以选对块block还是对记录record压缩,block压缩率比较高,输出压缩的配置基本相同:打开hive.exec.press.output.jvm重用在mrjob中,默认时每执行一个task就会启动一个jvm,如果task非常小而且碎,那么jvm启动和关闭耗时都会比较长。可以通过调节参数mapred.job.reuse.jvm.num.task来重用。例如将这个参数设置为,那么久代表同一个mrjob中顺序执行的各task可以重复使用一个jvm,减少启动和关闭开销,但是他对不同mrjob的task无效.采用合适的存储格式.数据倾斜数据倾斜原因:、join倾斜、聚合倾斜groupby倾斜:groupby字段中某个字段的值过多,导致处理这个值得reduce耗时很久解决方法:sethive.map.aggr=true;?--表示开启map端聚合sethive.groupby.skewindata=true;?注意:只能对单个字段聚合,?生成两个mapjob,第一个mapjob中map输出结果随机分布到reduce中,每个reduce做部分聚合操作,并输出结果,这样相同的groubkey有可能被分发到不同的reduce中,从而达到负载均衡的目的;第二个mapjob再根据预处理的数据结果按照groupbykey分布到reduce中,这个过程可以保证相同的key被分到同一个reduce中,最后完成最终的聚合操作.优化in、exists语句使用leftsemijoin替换in、exists.合并mapreduce操作multi-groupby是hive的一个非常好的特性,它使得hive中利用中间结果变更非常方便例如:from(selecta.status,b.schoolfromstatus_updateajoinprofileesbon(a.userid=b.suerid))subqinsertoverwirtetableapartition(ds=’--’)?selectsubq.school,count()groupbysubq.schoolinsertoverwritetablebpartition(ds=’--’)selectsubq.status,count()groupbysubq.status上述语句使用了multi-groupby特性联系groupby次数据,使用不同的groupbykey,这一特性可以减少一次mapreduce操作

  ⑸hivenotin通过什么实现

  ⑹目前hive不支持in或notin中包含查询子句的语法,所以只能通过leftjoin实现。假设有一个登陆表login(当天登陆记录,只有一个uid),和一个用户注册表regusers(当天注册用户,字段只有一个uid),这两个表都包含一个字段,uid。in查询如果要查询当天登陆的注册用户,需要用in查询,hivesql如下:selectlogin.uidfromloginleftouterjoinregusersonlogin.uid=regusers.uidwhereregusers.uidisnotnull如果login表和regusers表按天分区,字段是dt,那么查询年月号当天登陆的注册用户,hivesql如下:selectlogin.uidfromloginday_loginleftouterjoin(selectuidfromreguserswheredt=’’)day_regusersonday_login.uid=day_regusers.uidwhereday_login.dt=’’andday_regusers.uidisnotnullnotin查询如果要查询当天登陆的老用户(这里假设非当天注册用户就是老用户),需要用notin查询,hivesql如下:selectlogin.uidfromloginleftouterjoinregusersonlogin.uid=regusers.uidwhereregusers.uidisnull;如果login表和regusers表按天分区,字段是dt,那么查询年月号当天登陆的老用户,hivesql如下:selectlogin.uidfromloginday_loginleftouterjoin(selectuidfromreguserswheredt=’’)day_regusersonday_login.uid=day_regusers.uidwhereday_login.dt=’’andday_regusers.uidisnull;Hivejoin优化========================================================由于hive与传统关系型数据库面对的业务场景及底层技术架构都有着很大差异,因此,传统数据库领域的一些技能放到Hive中可能已不再适用。关于hive的优化与原理、应用的文章,前面也陆陆续续的介绍了一些,但大多都偏向理论层面,本文就介绍一个实例,从实例中一步步加深对hive调优的认识与意识。、需求需求我做了简化,很简单,两张表做个join,求指定城市,每天的pv,用传统的RDBMSSQL写出来就这样的:?SELECTt.statdate,c.ame,count(t.cookieid)FROMtmpdb.citycJOINecdata.ext_trackflowtON(t.area=c.ameORt.area=c.ameORt.area=c.ame)WHEREt.statdate》=’’andt.statdate《=’’ANDplatform=’pc’GROUPBYt.statdate,c.ame;怎么样?根据SQL看懂需求没问题吧?、非等值join问题然后把这条SQL贴到hive中去执行,然后你会发现报错了:?FAILED:SemanticException:Line:ORnotsupportedinJOINcurrently’ame’这是因为hive受限于MapReduce算法模型,只支持equi-joins(等值join,要实现上述的非等值join,你可以采用笛卡儿积(fullCartesianproduct来实现:?SELECTt.statdate,c.ame,count(t.cookieid)FROMtmpdb.citycJOINecdata.ext_trackflowtWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’AND(t.area=c.ameORt.area=c.ameORt.area=c.ame)GROUPBYt.statdate,c.ame;然后再拿着这条语句执行下。、优化:reducesidejoinVSCartesianproduct如果你真的把这条语句放到Hive上执行,然后恰好你有张表还非常大,那么恭喜你。。。集群管理员估计会找你的麻烦了。。。友情提示:笛卡儿积这种语句在Hive下慎用,大数据场景下的m*n映射结果你懂的。。。对此,Hive特意提供了一个环境变量:hive.mapred.mode=strict;防止笛卡儿积的执行:?FAILED:SemanticException:Instrictmode,cartesianproductisnotallowed.Ifyoureallywanttoperformtheoperation,sethive.mapred.mode=nonstrict从中的观察得知我们在on后面跟join条件,走的是reducesidejoin,如果你在where后跟则是走Cartesianproduct,但是这里单条sql又没法实现reducesidejoin,还有没有其它办法呢?、改写非等值join:unionall既然不允许非等值join,那我们换一下思路,多个子查询unionall,然后汇总:?SELECTdt,name,count(cid)FROM(SELECTt.statdatedt,c.amename,t.cookieidcidFROMtmpdb.citycJOINecdata.ext_trackflowtONt.area=c.ameWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’UNIONALLSELECTt.statdatedt,c.amename,t.cookieidcidFROMtmpdb.citycJOINecdata.ext_trackflowtONt.area=c.ameWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’UNIONALLSELECTt.statdatedt,c.amename,t.cookieidcidFROMtmpdb.citycJOINecdata.ext_trackflowtONt.area=c.ameWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’)tmp_trackflowGROUPBYdt,name;、优化:mapsidejoin上述语句走的是reducesidejoin,从我们的需求及业务得知,tmpdb.city是一张字典表,数据量很小,因此我们可以试试把上述的语句改写成mapjoin:?SELECTdt,name,count(cid)FROM(SELECT/*+MAPJOIN(c)*/t.statdatedt,c.amename,t.cookieidcidFROMtmpdb.citycJOINecdata.ext_trackflowtONt.area=c.ameWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’UNIONALLSELECT/*+MAPJOIN(c)*/t.statdatedt,c.amename,t.cookieidcidFROMtmpdb.citycJOINecdata.ext_trackflowtONt.area=c.ameWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’UNIONALLSELECT/*+MAPJOIN(c)*/t.statdatedt,c.amename,t.cookieidcidFROMtmpdb.citycJOINecdata.ext_trackflowtONt.area=c.ameWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’)tmp_trackflowGROUPBYdt,name;、优化无极限:开启parallel和控制reduce个数上述语句执行时,你可以看到执行计划和状态信息,以及结合你的unionall语句可知,三个union语句之间没有依赖关系,其实是可以并行执行的:?explainSQL......STAGEDEPENDENCIES:Stage-isarootstageStage-dependsonstages:Stage-Stage-dependsonstages:Stage-Stage-dependsonstages:Stage-,Stage-,Stage-Stage-isarootstageStage-dependsonstages:Stage-Stage-dependsonstages:Stage-Stage-isarootstageStage-dependsonstages:Stage-Stage-dependsonstages:Stage-Stage-isarootstage...我们在SQL前加上如下环境变量选项:?setmapred.reduce.tasks=;sethive.exec.parallel=true;让执行计划中的Stage-、Stage-、Stage-并行执行,并控制好reducetask个数。完整的语句如下:?hive-e“SETmapred.reduce.tasks=;SEThive.exec.parallel=TRUE;SELECTdt,name,count(cid)FROM(SELECT/*+MAPJOIN(c)*/t.statdatedt,c.amename,t.cookieidcidFROMtmpdb.citycJOINecdata.ext_trackflowtONt.area=c.ameWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’UNIONALLSELECT/*+MAPJOIN(c)*/t.statdatedt,c.amename,t.cookieidcidFROMtmpdb.citycJOINecdata.ext_trackflowtONt.area=c.ameWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’UNIONALLSELECT/*+MAPJOIN(c)*/t.statdatedt,c.amename,t.cookieidcidFROMtmpdb.citycJOINecdata.ext_trackflowtONt.area=c.ameWHEREt.statdate》=’’ANDt.statdate《=’’ANDplatform=’pc’)tmp_trackflowGROUPBYdt,name;“》a.txt最后的优化效果是:中的语句三个小时没出结果。。。比快倍左右,比快倍左右,最终min出结果。

  ⑺【Hive】HiveJoin介绍

  ⑻Hive中的Join只支持等值Join,也就是说Joinon中的on里面表之间连接条件只能是=,不能是《,》等符号。此外,on中的等值连接之间只能是and,不能是or。

  ⑼Hive执行引擎会将HQL“翻译”成为map-reduce任务,在执行表的Join操作时,如果多个表中每个表都使用同一个列进行连接(出现在Joinon子句中,则只会生成一个MRJob:

  ⑽三个表a、b、c都分别使用了同一个字段进行连接,亦即同一个字段同时出现在两个Join子句中,从而只生成一个MRJob。

  ⑾如果多表中,其中存在一个表使用了至少个字段进行连接(同一个表的至少个列出现在Join子句中,则会至少生成个MRJob:

  ⑿三个表基于个字段进行连接,这两个字段b.key和b.key同时出现在b表中。连接的过程是这样的:首先a和b表基于a.key和b.key进行连接,对应着第一个MRJob;表a和b连接的结果,再和c进行连接,对应着第二个MRJob。

  ⒀这是因为Map输出时候以Joinon条件中的列为key,如果Join有多个关联键,则以这些关联键的组合作为key,Map根据Key分发数据给Reduce端,具体的Join是在Reduce操作中完成,因此,如果多表基于不同的列做Join,则无法在一轮MR任务中将所有相关数据shuffle到同一个Reduce操作中。

  ⒁Hive支持常用的SQLJoin语句,例如内连接、左外连接、右外连接以及Hive独有的map端连接。其中map端连接是用于优化Hive连接查询的一个重要技巧。

  ⒂employee员工表:

  ⒃多张表进行内连接操作时,只有所有表中与on条件中相匹配的数据才会显示,类似取交集。

  ⒄JOIN操作符左边表中符合where条件的所有记录都会被保留,JOIN操作符右边表中如果没有符合on后面连接条件的记录,则从右边表中选出的列为NULL,如果没有where条件,则左边表中的记录都被保留。

  ⒅标准查询关键字执行顺序为from-》on-》where-》groupby-》having-》orderby,on是先对表进行筛选后再关联的,left关联则on只对右表有效,左表都要选出来。

  ⒆对于大量的数据,在编写SQL时尽量用where条件过滤掉不符合条件的数据是有益的。但是对于左外连接和右外连接,where条件是在on条件执行之后才会执行,on条件会产生一个临时表,where条件是对这个临时表进行过滤。

  ⒇因此为了优化HiveSQL执行的效率,在需要使用外连接的场景,如果是要条件查询后才连接应该把查询件放置于on后,如果是想再连接完毕后才筛选就应把条件放置于where后面,对主表的筛选要用where条件。

  ⒈特别要注意的是,如果是需要对主表过滤之后再和从表做左关联,最好将主表写成子查询的形式,可以减少主表的数据量:

  ⒉RIGHTOUTERJOIN,与LEFTOUTERJOIN相对,JOIN操作符右边表中符合where条件的所有记录都会被保留,JOIN操作符左边表中如果没有符合on后面连接条件的记录,则从左边表中选出的列为NULL。

  ⒊保留满足where条件的两个表的数据,类似并集,没有符合连接条件的字段使用NULL填充。

  ⒋以LEFTSEMIJOIN关键字前面的表为主表,返回主表的KEY也在副表中的记录。在早期的Hive版本中,不支持标准SQL中的IN或EXISTS的功能,可以使用LEFTSEMIJOIN实现类似的功能。

  ⒌笛卡尔积是一种连接,表示左边表的行数乘以右边表的行数。

  ⒍Hive中的Join可分为monJoin(Reduce阶段完成join和MapJoin(Map阶段完成join。

  ⒎如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会默认把执行monJoin,即在Reduce阶段完成join。整个过程包含Map、Shuffle、Reduce阶段。

  ⒏以下面HQL为例,图解其过程:

  ⒐MapJoin通常用于一个很小的表和一个大表进行join的场景,具体小表有多小,由参数hive.mapjoin.smalltable.filesize来决定,该参数表示小表的总大小,默认值为字节,即M。

  ⒑Hive.之前,需要使用hint提示/+mapjoin(table)/才会执行MapJoin,否则执行monJoin,但在.版本之后,默认自动会转换MapJoin,由参数hive.auto.convert.join来控制,默认为true。

  ⒒如上图中的流程,首先TaskA在客户端本地执行,负责扫描小表b的数据,将其转换成一个HashTable的数据结构,并写入本地的文件中,之后将该文件加载到DistributeCache中。

  ⒓接下来是TaskB,该任务是一个没有Reduce的MR,启动MapTasks扫描大表a,在Map阶段,根据a的每一条记录去和DistributeCache中b表对应的HashTable关联,并直接输出结果。

  ⒔由于MapJoin没有Reduce,所以由Map直接输出结果文件,有多少个MapTask,就有多少个结果文件。

  ⒕MapJoin效率比monJoin效率好,但总会有“小表”条件不满足的时候。这就需要bucketmapjoin了。

  ⒖Bucketmapjoin需要待连接的两个表在连接字段上进行分桶(每个分桶对应hdfs上的一个文件,而且小表的桶数需要时大表桶数的倍数。

  ⒗这样,my_user表就对应个桶,数据根据uid的hashvalue与取余,然后被分发导不同的桶中。

  ⒘如果两个表在连接字段上分桶,则可以执行bucketmapjoin了,具体的:

  ⒙对于bucketmapjoin中的两个表,如果每个桶内分区字段也是有序的,则还可以进行sortmergebucketmapjoin。

  ⒚这样一来当两边bucket要做局部join的时候,只需要用类似mergesort算法中的merge操作一样把两个bucket顺序遍历一遍即可完成,小表的数据可以每次只读取一部分,然后还是用大表一行一行的去匹配,这样的join没有限制内存的大小.并且也可以执行全外连接。

  ⒛进行sortmergebucketmapjoin时,需要设置的属性为:

  Join的过程中,Map结束之后,会将相同的Key的数据shuffle到同一个Reduce中,如果数据分布均匀的话,每个Reduce处理的数据量大体上是比较均衡的,但是若明显存在数据倾斜的时候,会出现某些Reducer处理的数据量过大,从而使得该节点的处理时间过长,成为瓶颈。

  大表与大表关联,如果其中一张表的多是空值或者比较多,容易shuffle给一个reduce,造成运行慢。

  这种情况可以对异常值赋一个随机值来分散key,均匀分配给多个reduce去执行,比如:

  当key值都是有效值时,解决办法为:

  Hive在运行的时候无法判断哪个key会产生倾斜,所以使用hive.skewjoin.key参数控制倾斜的阈值,如果超过这个值,新的值会发送给那些还没有达到的reduce,一般可以设置成待处理的总记录数/reduce个数的-倍。

  Hive基础二(join原理和机制,join的几种类型,数据倾斜简单处理.Hive:JOIN及JOIN优化.hive中关于常见数据倾斜的处理

  thinkphp中join方法怎么用

  不用加前缀,但是需要用C(’DB_PREFIX’)连接表名。$list=M(’ordero’)-》field(’o.*,c.title’)-》where($map)-》join(’leftjoin’.C(’DB_PREFIX’).’carcONo.car_id=c.id’)-》order(’o.iddesc’)-》select();

  hive数据倾斜及处理

  火山日常啰嗦学习了一些大数据的相关框架后,发现应用层的东西确实不难,真正难的都是底层原理,所以我查看了很多资料,借鉴了前人的方法再加上自己的理解,写下了这篇文章。数据倾斜的直白概念:数据倾斜就是数据的分布不平衡,某些地方特别多,某些地方又特别少,导致的在处理数据的时候,有些很快就处理完了,而有些又迟迟未能处理完,导致整体任务最终迟迟无法完成,这种现象就是数据倾斜。针对mapreduce的过程来说就是,有多个reduce,其中有一个或者若干个reduce要处理的数据量特别大,而其他的reduce处理的数据量则比较小,那么这些数据量小的reduce很快就可以完成,而数据量大的则需要很多时间,导致整个任务一直在等它而迟迟无法完成。跑mr任务时常见的reduce的进度总是卡在%,这种现象很大可能就是数据倾斜造成的。产生数据倾斜的原因:key的分布不均匀或者说某些key太集中。上面就说过,reduce的数据量大小差异过大,而reduce的数据是分区的结果,分区是对key求hash值,根据hash值决定该key被分到某个分区,进而进入到某个reduce,而如果key很集中或者相同,那么计算得到它们的hash值可能一样,那么就会被分配到同一个reduce,就会造成这个reduce所要处理的数据量过大。业务数据自身的特性。比如某些业务数据作为key的字段本就很集中,那么结果肯定会导致数据倾斜啊。还有其他的一些原因,但是,根本原因还是key的分布不均匀,而其他的原因就是会造成key不均匀,进而导致数据倾斜的后果,所以说根本原因是key的分布不均匀。既然有数据倾斜这种现象,就必须要有数据倾斜对应的处理方案啊。简单地说数据倾斜这种现象导致的任务迟迟不能完成,耗费了太多时间,极大地影响了性能,所以我们数据倾斜的解决方案设计思路就是往如何提高性能,即如何缩短任务的处理时间这方面考虑的,而要提高性能,就要让key分布相对均衡,所以我们的终极目标就是考虑如何预处理数据才能够使得它的key分布均匀。常见的数据倾斜处理方案:设置参数设置hive.map.aggr=true//开启map端部分聚合功能,就是将key相同的归到一起,减少数据量,这样就可以相对地减少进入reduce的数据量,在一定程度上可以提高性能,当然,如果数据的减少量微乎其微,那对性能的影响几乎没啥变化。设置hive.groupby.skewindata=true//如果发生了数据倾斜就可以通过它来进行负载均衡。当选项设定为true,生成的查询计划会有两个MRJob。第一个MRJob中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MRJob再根据预处理的数据结果按照Key分布到Reduce中(这个过程是按照key的hash值进行分区的,不同于mrjob的随机分配,这次可以保证相同的Key被分布到同一个Reduce中,最后完成最终的聚合操作。所以它主要就是先通过第一个mrjob将key随机分配到reduce,使得会造成数据倾斜的key可能被分配到不同的reduce上,从而达到负载均衡的目的。到第二个mrjob中,因为第一个mrjob已经在reduce中对这些数据进行了部分聚合(就像单词统计的例子,a这个字母在不同的reduce中,已经算出它在每个reduce中的个数,但是最终的总的个数还没算出来,那么就将它传到第二个mrjob,这样就可以得到总的单词个数,所以这里直接进行最后的聚合就可以了。hive.exec.reducers.bytes.per.reducer=(单位是字节每个reduce能够处理的数据量大小,默认是Ghive.exec.reducers.max=最大可以开启的reduce个数,默认是个在只配了hive.exec.reducers.bytes.per.reducer以及hive.exec.reducers.max的情况下,实际的reduce个数会根据实际的数据总量/每个reduce处理的数据量来决定。mapred.reduce.tasks=-实际运行的reduce个数,默认是-,可以认为指定,但是如果认为在此指定了,那么就不会通过实际的总数据量/hive.exec.reducers.bytes.per.reducer来决定reduce的个数了。sql语句优化给几个具体的场景以及在这些场景下的处理方案:进行表的join这种业务操作时,经常会产生数据倾斜。原因就是这些业务数据本就存在key会分布不均匀的风险,所以我们join时不能使用普通的join(reduce端join或者可以使用普通join,但是是优化后的。但是这种操作有个前提条件就是仅适用于小表join大表,而小表怎么定义它的大小,多小的表才算小表,这里有个参数可以确定的(但是这个参数名我暂时忘记了,如果小表的数据大小小于这个值,就可以使用mapjoin,而是在这种情况下是自动使用mapjoin这种方案的。所以如果是大小表join,直接用mapjoin,避免数据倾斜。方法:(普通joinselect*fromlogajoinusersbon(a.user_idisnotnullanda.user_id=b.user_id;这是属于表的内连接的,两张表不满足条件的记录都不保留。方法:检测到user_id是null时给它赋予一个新值(这个新值由一个字符串(比如我自己给它定一个hive加上一个随机数组成,这样就可以将原来集中的key分散开来,也避免了数据倾斜的风险。而且因为这些数据本来就是无效数据,根本不会出现在结果表中,所以,这样处理user_id(由一个字符串(比如我自己给它定一个hive加上一个随机数,它也无法关联的,因为有效的数据的user_id没有这种形式的,所以就算这些无效数据出现在不同的reduce中还是不会影响结果的,我这样处理只是为了将它们分散开而已,所以用这种方法处理,结果表中也不会出现null这些无效数据,跟过滤处理方案得到的结果是一样的。(普通joinselect*fromlogajoinusersboncasewhena.user_idisnullthenconcat(‘hive’,rand())elsea.user_idend=b.user_id;但是这两种方案只是适用于大表join大表的内连接,两张表的无效数据都不保留。但是如果对于左外连接或者右外连接这种情况,即使驱动表中某些记录在另一张表中没有数据与它对应,但我们是依然需要保留驱动表的这些数据的,那该怎么办呢?其实很简单,只需要将上述方法得到的结果再与驱动表的这些无数据取并集就可以了。如下:select*fromlogaleftouterjoinusersbona.user_idisnotnullanda.user_id=b.user_idunionallselect*fromlogawherea.user_idisnull;)虽然都是大表,但是呢对于某些业务数据而言,其有用的部分只占它所在表的很少一部分,那么我们就可以将它们先取出来,得到的结果应该是一张小表,那么就可以使用mapjoin来避免数据倾斜了。场景:用户表中user_id字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的Join操作时,因为我们在连接时要进行user_id的比较,所以需要user_id的类型都相同,如果我们选择将log表中的String类型转换为int类型,那么就可能会出现这种情况:String类型转换为int类型得到的都是null值(这就是类型转换的问题了,String类型数据转换为int类型会失败,数据丢失,就会赋null值,如果所有的String类型的user_id都变成了null,那么就又出现了集中的key,分区后就又会导致数据倾斜。所以我们进行类型转换时不能选择将String类型转换为int,而应该将int类型转换为String,因为int转换为String不会出问题,int类型原来的值是什么,转换为String后对应的字符串就会是什么,形式没变,只是类型变了而已。解决方法:把int类型转换成字符串类型select*fromusersajoinlogsbon(a.usr_id=cast(b.user_idasstring));比如有一份日志,要你从日志中统计某天有多少个用户访问网站,即统计有多少个不同的user_id;但是呢这个网站却又恰巧遭到攻击,日志中大部分都是同一个user_id的记录,其他的user_id属于正常访问,访问量不会很大,在这种情况下,当你直接使用count(distinctuser_id)时,这也是要跑mr任务的啊,这时这些大量的相同的user_id就是集中的key了,结果就是通过分区它们都被分到一个reduce中,就会造成这个reduce处理的数据特别大,而其中的reduce处理的数据都很小,所以就会造成数据倾斜。那么要怎么优化呢?方法:可以先找出这个user_id是什么,过滤掉它,然后通过count(distinctuser_id)计算出剩余的那些user_id的个数,最后再加(这个就是那个被过滤掉的user_id,虽然它有大量的记录,但是ser_id相同的都是同一个用户,而我们要计算的就是用户数sql语句展示:分组求和后降序排序,就可以得到这个数据量最大的user_id是什么,然后我们下一步操作时就过滤它,等计算完其他的再加上它这一个。selectuser_id,count(user_id)fromloggroupbyuser_iddesclimit;selectcount(distinctuser_id+assumfromlog;sum就是最终的结果--用户数方法:我们可以先通过groupby分组,然后再在分组得到的结果的基础之上进行countsql语句展示:selectcount(*)from(selectuser_idfromloggroupbyuser_id)new_log;总的来说就是,数据倾斜的根源是key分布不均匀,所以应对方案要么是从源头解决(不让数据分区,直接在map端搞定,要么就是在分区时将这些集中却无效的key过滤(清洗掉,或者是想办法将这些key打乱,让它们进入到不同的reduce中。性能调优是指通过调整使得机器处理任务的速度更快,所花的时间更少,而数据倾斜的处理是hive性能调优的一部分,通过处理能够大大减少任务的运行时间。除了数据倾斜的处理之外,hive的优化还有其他方面的,例如where子句优化:select*fromaleftouterjoinbon(a.key=b.key)wherea.date=’--’andb.date=’--’;这是一个左外连接。这个sql语句执行的结果是:得到的结果是表a与表b的连接表,且表中的记录的date都是’--’。而这个sql语句的执行过程是:逐条获取到a表的记录,然后扫描b表,寻找字段key值为a.key的记录,找到后将b表的这条记录连接到a表上,然后判断连接后的这条记录是否满足条件a.date=’--’andb.date=’--’,如果满足,则显示,否则,丢弃。因为这是一个左外连接,且a为驱动表,连接时在a中发现key而在b中没有发现与之相等的key时,b中的列将置为null,包括列date,一个不为null,一个为null,这样后边的where就没有用了。简答的说这个方案的做法就是先按连接条件进行连接,连接后再看where条件,如果不满足就丢弃,那之前连接所做的那些功夫就浪费了,白白耗费了资源(cpu等,增加了运行的总时间,如果有一种方案可以在未进行连接之前就直接判断出不满足最终的条件,那么就可以直接丢弃它,这样对于这样的记录就不要浪费资源以及时间去连接了,这样也是能提升性能的,下面就看看这种方案:sql语句:将刚才的where限制条件直接放到on里面,那么就变成了满足这三个条件才会进行连接,不满足的直接过滤掉,就像上面所说的,少了无效连接那一步,就相对地节约了时间,如果这样的无效连接的记录很多的话,那么采用这种改进版的方案无疑能够较大程度地提高性能。select*fromaleftouterjoinbon(a.key=b.keyanda.date=’--’andb.date=’--’;不管怎么说,我们在运行任务时,总是希望能加快运行速度,缩短运行时间,更快地得到结果,即提升性能,这是我们的目的,这就是我们所谓的性能调优。关于小表join大表的补充:表join时的操作是这样的:当操作到驱动表的某条记录时,就会全局扫描另一张表,寻找满足条件的记录,而当扫描它时,为了读取速度更快,一般都选先将它加载到内存,而内存的大小是有限的,为了不占据过多的内存或者避免内存溢出,加载进入内存的表一般是小表,即数据量比较小,mapjoin就是这样做的。即驱动表不放进内存,而另一张表(即要连接到驱动表的那一张表就要先加载进内存,为了扫描速度更快,提高性能。比如select*fromaleftouterjoinbon(a.key=b.key);左外连接,驱动表是a,表b的记录是要被连接到表a的,所以每在a上连接一条记录就要被全局扫描一次的表是b,所以表b应先加载到内存(前提是表b是小表,如果是大表的话,估计会产生oom异常--outofmemory内存溢出异常。select*fromaarightouterjoinbbon(a.key=b.key);右外连接,驱动表是bb,aa应先加载到内存(前提是小表。ps:希望我的分享能帮助到有需要的伙伴哦。我不是大神的哦,如果文中有误,还请大家不吝赐教,帮忙指正,谢谢了!!!

  hiveleftsemijoinmap是在哪个阶段

  hive不支持’leftjoin’的写法;hive的leftouterjoin:如果右边有多行和左边表对应,就每一行都映射输出;如果右边没有行与左边行对应,就输出左边行,右边表字段为NULL;hive的leftsemijoin:相当于SQL的in语句以下为两个测试数据表建表语句...

  大数据开发工程师Hive(Hive如何进行优化)

  针对hive中表的存储格式通常有textfile和orc,压缩格式一般使用snappy。相比于textfile格式存储,orc占有更少的存储。因为hive底层使用MR计算架构,数据流是hdfs到磁盘再到hdfs,而且会有很多次IO读写操作,所以使用orc数据格式和snappy压缩策略可以降低IO读写,还能降低网络传输量,这样在一定程度上可以节省存储空间,还能提升hql的执行效率;

  调节Jvm参数,重用Jvm;

  合理设置Map个数;

  合理设置Reduce个数;

  Hive创建表的时候,可以建分区表,分桶表;

  Hive创建表的时候,可以指定数据存储格式:TextFile、SequenceFile、RCfile、ORCfile;

  列裁剪,在查询时只读取需要的列,避免全列扫描,不要使用select*fromtable;

  分区裁剪:在查询时只读取需要分区的数据,避免全表扫描;

  开启谓词下推:sethive.optimize.ppd=true,默认是true:

  a.将Sql语句中的where谓词逻辑都尽可能提前执行,减少下游处理的数据量;

  a.开启MapJoin:sethive.auto.convert.join=true:

  b.MapJoin是将Join双方比较小的那个表直接分发到各个Map进程的内存中,在Map进程中进行Join操作,这样就不用进行Reduce步骤,从而提高了速度(大表leftjoin小表才有效,小表leftjoin大表会失效);

  a.SMBJoin:SortMergeBucketJoin(数据不仅分桶了,而且每个桶数据是排好序了);

  b.开启SMBJoin之后,底层是根据两个表join字段进行分桶存储,这样的话,两张表就变为了基于桶之间join关联查询,而不是基于整张表的join,减少了笛卡尔积;

  少用in,用leftsemijoin替代in:

  a.原始写法:selecta.id,a.namefromawherea.idin(selectb.idfromb);

  b.用join改写:selecta.id,a.namefromajoinbona.id=b.id;

  c.leftsemijoin改写:selecta.id,a.namefromaleftsemijoinbona.id=b.id;

  用unionall代替union,因为unionall不需要去重,也不需要排序,效率高于union;

  (每天小题,进步点点)

  TypeORM无关联关系的mysql多表连接查询

  ??TypeORM官方给的文档中,多表查询时使用的是通过实体关系进行leftjoin查询,我们知道TypeORM实体关系实际上是通过mysql的外键实现的。在实际开发中,外键因为有诸多限制不被推荐使用,大部分的都是无关系的表连接。经过几天的查找资料和摸索,找到了两种查询的方法,总结一下,如果大家有其他好的方法,欢迎留言讨论。??这种方法使用getRawOne获取到sql查询后的原始数据,因为TypeORM会用别名,所以这里用select对字段进行了重命名,这个写法需要对每个需要的字段名进行重命名,否则返回的字段名称会带上表名。??第二种方法使用leftJoinAndMapOne作字段映射,如果一对多可以使用leftJoinAndMapMany。这样就不用挨个对字段重命名,但是可能存在嵌套较深的问题。??以上是常用的两种表连接的方法,每个都有其优缺点,可以根据情况选择使用。两外附上这两种方法的出处:、

  求助,关于mapjoin

  关于mapjoin,有张亿数据的大表,要leftouterjoin一张几百行数据的小表,如何mapjoinselect/*+MAPJOIN(A)*/字段from小表Arightouterjoin大表BonA.XX=B.XX吗?这个?

您可能感兴趣的文章:

相关文章