Hive数据倾斜常见问题和解决方案
目录
Hive数据倾斜是面试中常问的问题,这里我们需要很熟练地能举出常见的数据倾斜的例子并且给出解决方案。
我们可以通过sql语句前面加expalin来具体查看这条语句的执行计划 通过观察它的一些参数来辅助调优


数据倾斜是由于数据分布不均匀,造成数据大量的集中到一点,造成数据热点的现象。
主要表现:任务进度长时间维持在 99%或者 100%的附近,查看任务监控页面,发现只有少量 reduce 子任务未完成,因为其处理的数据量和其他的 reduce 差异过大。 单一 reduce 处理的记录数和平均记录数相差太大,通常达到好几倍之多,最长时间远大于平均时长。
这里Hive自动帮我们把小表放到缓存当中了。也就是我们所熟知的mapjoin,在学习Hadoop中就已经使用过。
以前需要我们手动调:set hive.auto.convert.join=true
一般小表的大小是25M左右,想要改变其大小只需set hive.mapjoin.smalltable.filesize=25000000
以前join的时候小表必须在左边,现在底层优化了,无所谓放到左边右边了。
空key可能是异常数据,两个表联接时,联接的字段作为key,可能有很多null值,也可能集中出现在某个值上。这样就导致了他们经过计算得出的哈希值都一样,然后把它们都放到一个reduce里面,导致这几个reduce的压力过大,其他reduce很轻松的场面,也就是我们所谓的数据倾斜。
这里我们有两种常用的解决办法:第一种是将两表联接之前就去掉这些null值,然后再union all加上是空值的全部数据。比如要联接user和log:
select * from log a join user b on a.userid is not null and a.userid=b.userid union all select * from log c where c.userid is null;
第二种办法就是赋予空值新的key值,通过随机数将他们赋给不同的reduce:
这里什么意思呢?就是null现在通过计算不都是一个哈希值嘛,那就给他们赋随机数,这样通过计算就会分配到不同的分区了。
select * from log a left join user b on case when a.userid is null then concat('hive',rand()) else a.userid end =b.userid;
比如两个表联接,联接的字段是userid,一个表的userid是string类型,一个表的是int类型,那这样默认按照int来计算哈希的话,那么string类型的都会被分到同一组,易发生数据倾斜。
解决办法就是把数字类型 id 转换成 string 类型的 id,或者统一即可。
如果此时的小表不大不小,不能发生mapjoin,有什么优化方法呢?假如联接的字段是userid,这里如果这个“大表”或者“小表”有比较多重复的userid,那么我们也可以优化。
我们这里假设大表有较多重复的userid,解决方案就是就是先给“大表”的userid去重然后再联接另一个表,此时去重后大表可能会变成小表,这样又可以mapjoin,查询完以后再右连接原先的这个大表。比如这时的log表是大表,有很多重复的userid,users表是小表,但也超过了25M。
select from log a left join (select d* from (select distinct userid from log)c join users d on c.userid=d.userid)x on a.userid=x.userid
两个大表联查,分桶优化,根据id分桶,id是字符型数值,通过计算哈希值会计算出自己在第几桶,所以一个桶对应一个桶就行,这样效率提高很多。
一个桶对应一个桶,0桶对应0桶联查,1桶对应1桶联查...(因为一样的id肯定在一个对应的桶里)

代码演示:




group by引起的倾斜主要是输入数据行按照group by列分布不均匀引起的。
比如,有个key值有100W个a,此时直接做分组的话,这100W个a将会分到同一个reduce中,这一个节点处理的数据远大于其他节点处理的数据,造成数据倾斜,跑不出数据。其原因就是有大量的key集中分配到了同一个reduce,那么我们的解决思路就是将这些key值打散,使起分散到多个reduce节点处理即可,达到负载均衡的效果。解决办法:(2)可以不动

在Hive开发过程中,应该小心使用count distinct,因为很容易引起性能问题,比如下面的SQL:
select count(distinct userid) from t1;
由于必须去重,因此Hive将会把Map阶段的输出全部分布到一个Reduce Task上,此时很容易引起性能问题。对于这种情况,可以通过先group by再count的方式来优化,优化后的SQL如下:
select count(*) from (select user from t1 group by userid) a;
其原理为:利用group by去重,再统计group by的行数目(不过这种方式需要注意数据倾斜的问题)。

谓词下推 用在SQL优化上来说 就是先过滤再做聚合等操作
因为两个表的关联字段是id 想要在关联以后在用where过滤 实际上底层已经优化了 关联之前就将两个表过滤了 但有时候sql写的长的时候 谓词下推会失效 所以有点不靠谱的

(该图来自知乎)





我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声
首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有, 也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决