hive常见⾯试题
hive常见⾯试题
1、⼤表join⼩表产⽣的问题,怎么解决?
⼤表join⼩表,独钟爱mapjoin;
MapJoin通常⽤于⼀个很⼩的表和⼀个⼤表进⾏join的场景,具体⼩表有多⼩,由参数hive.mapjoin.smalltable.filesize来决定,该参数表⽰⼩表的总⼤⼩,默认值为25000000字节,即25M。
在0.7版本之后,默认⾃动会转换Map Join;
Mapjoin分为两个阶段:
1. 通过mapreduce local task,将⼩表读⼊内存,⽣成HashTableFiles上传⾄Distributed Cache中,这⾥会将HashTableFiles进⾏
压缩。
2. MapReduce Job在map节点,每个mapper从distributed cache读取HashTableFiles到内存中,顺序扫
描⼤表,在map阶段直接
进⾏join,将数据传递给下⼀个mapreduce任务。
2、长尾问题
SQL在Join执⾏阶段会将Join Key相同的数据分发到同⼀个执⾏Instance上处理。如果某个Key上的数据量⽐较多,会导致该Instance执⾏时间⽐其他Instance执⾏时间长。执⾏⽇志中该Join Task的⼤部分Instance都已执⾏完成,但少数⼏个Instance⼀直处于执⾏中,这种现象称之为长尾。
⼩表长尾:使⽤mapjoin解决。
热点值长尾:可以取出热点数据和⾮热点数据分别处理,最后合并。
空值长尾:使⽤coalesce(left_table.key,rand()*9999)将key为空的情况赋予随机值,来避免空值造成长尾。
奥茨冰人map长尾:map端读取⽂件不均匀造成长尾。想办法合并源⽂件,或者取消split每个⼩⽂件占⼀个spilt。只能调节splitsize增加mapper数量,使数据分⽚更⼩,期望获得更好分配。
reduce长尾:由于Distinct操作的存在,数据⽆法在Map端的Shuffle阶段根据Group By先做⼀次聚合操作,减少传输的数据量,⽽是将所有的数据都传输到Reduce端,当Key的数据分发不均匀时,就会导致Reduce端长尾,特别当多个Distinct同时出现在⼀段SQL代码中时,数据会被分发多次,不仅会造成数据膨胀N倍,也会把长尾现象放⼤N倍。
解决⽅法:使⽤group by替代distinct,group by以及存在,则将distinct拆分为另外的sql。
3、udf、udaf、udtf区别
虽然hive提供了丰富的函数⽀持,但在实际业务中,数据往往难以被现有函数处理(⽐如⽤户⽇志的json数据,通⽤函数往往不能很好的处理),基于这种情况,hive提供了3个抽象接⼝。
UDF操作作⽤于单个数据⾏,并且产⽣⼀个数据⾏作为输出。⼤多数函数都属于这⼀类(⽐如数学函数和字符串函数)。⼀对⼀。
UDAF 接受多个输⼊数据⾏,并产⽣⼀个输出数据⾏。像COUNT和MAX这样的函数就是聚集函数。多对⼀。
UDTF 操作作⽤于单个数据⾏,并且产⽣多个数据⾏,⼀个表作为输出。lateral view explore()。⼀对多。
⾃定义函数的实现流程:
继承对应的类(GenericUDF),在evaluate函数⾥⾯编写业务代码。
打包,并上传到服务器。
在hive中创建临时/永久函数,使⽤⾃定义函数类似hive⾃带的函数。
4、hive有哪些保存元数据的⽅式,都有什么特点。
1. 内存数据库derby,安装⼩,但数据存在内存,不稳定,只有允许⼀个连接,重新进⼊hive数据不⼀样。⼀般不使⽤。
2. mysql数据库,数据存储格式可以⾃⼰设置,持久化好,查询⽅便,允许多个连接。⼀般使⽤这种。
5、hive内部表和外部表的区别,⽣成环境中为什么建议使⽤外部表?
内部表:加载数据到hive所在的hdfs⽬录中,删除时,元数据和数据⽂件都删除。
外部表:不加载数据到hive所在的hdfs⽬录,删除时,只删除表结构。(从hdfs⾓度可以删除外部表
数据,所以使⽤hdfs操作需谨慎)。外部表相对来说更加安全些,数据组织也更加灵活,⽅便共享源数据。
扩展:什么时候使⽤内部表,什么时候使⽤外部表
1. 每天采集的ng⽇志和埋点⽇志,在存储的时候建议使⽤外部表,因为⽇志数据是采集程序实时采集进来的,⼀旦被误删,恢复起来⾮常
⿇烦。⽽且外部表⽅便数据的共享。
2. 抽取过来的业务数据,其实⽤外部表或者内部表问题都不⼤,就算被误删,恢复起来也是很快的,如果需要对数据内容和元数据进⾏
紧凑的管理, 那还是建议使⽤内部表。也就是说,即使这些业务数据是在原始数据层,也可以使⽤内部表。
3. 在做统计分析时候⽤到的中间表,结果表可以使⽤内部表,因为这些数据不需要共享,使⽤内部表更为合适。并且很多时候结果分区
表我们只需要保留最近3天的数据,⽤外部表的时候删除分区时⽆法删除数据。
总结:恢复⽐较⿇烦甚⾄难以恢复的数据,肯定需要使⽤外部表;其它时候更加业务需求判断是否选择内部表。
6、inrt into和override write区别?
inrt into:将数据写到表中(追加)
override write:将数据覆盖之前的内容
7、hive的判断函数有哪些
条件函数
1. if(boolean testCondition, T valueTrue, T valueFalOrNull)
2. nvl(T)
3. coalesce(T v1, T v2, …)
4. ca a when b then c [when d then e]* [el f] end
5. isnull(a)
6. isnotnull(a)
8、简单描述⼀下hive的功能?⽤hive创建表有⼏种⽅式?表有哪⼏种?
hive主要是做离线分析的。(扩展知识⾯试不问别回:可以使⽤spark引擎)
hive建表有三种⽅式
1. 直接建表
2. 查询建表法(通过AS查询语句完成建表:将⼦查询的结果存在新表,有数据,⼀般⽤于中间表)
3. like建表法(会创建结果完全相同的表,但是没有数据)
hive表有两种:内部表和外部表
ps:⾯试⼩技巧:不能给⾃⼰挖坑,⾯试官问什么答什么,除⾮是感觉⾃⼰是相关⽅⾯的⼤佬,否则不能随便引导话题(尤其是菜鸟,知识不够深,⾯试官多反问⼏次就直接破功了)
9、⽇志数据选择什么压缩算法
线上业务每天产⽣的业务⽇志(压缩后>=3G),每天需要加载到hive的log表中,将每天产⽣的业务⽇志在压缩之后load到hive的log表时,最好使⽤的压缩算法是哪个,并说明其原因?
选择lzo,因为算法可以切分,压缩率⽐较⾼,解压缩速度很快,⾮常适合⽇志。
10、若在hive中建⽴分区仍不能优化查询效率,建表时如何优化
可以重新建表为分区分桶表(分区是创建不同⽬录,分桶是创建不同⽂件)
11、union all和union的区别
union 会对结果去重合并,同时进⾏默认规则的排序
union all不会对结果去重处理,不进⾏排序
12、如何解决hive数据倾斜的问题
表现:任务进度长时间维持在99%(或100%),查看任务监控页⾯,发现只有少量(1个或⼏个)reduce⼦任务未完成。因为其处理的数据量和其他reduce差异过⼤。
原因:某个reduce的数据输⼊量远远⼤于其他reduce数据的输⼊量
sql本⾝导致的倾斜
group by
1. 使group by的维度变得更细
2. 在原分组key上添加随机数聚合,然后对结果去掉随机数后再分组聚合
3. 在join时如果有⼤量null的join key,则可以将null转换成随机值,避免聚集
count(distinct)
使⽤group by替代,可以先将值为空的记录单独处理(特殊值),再和其它计算结果进⾏union
不同数据类型关联产⽣数据倾斜
情形:⽐如⽤户表中 ur_id 字段为 int,log 表中 ur_id 字段既有 string 类型也有 int 类型。当按照 ur_id 进⾏两个表的 Join 操作时。
后果:处理此特殊值的 reduce 耗时;只有⼀个 reduce 任务
默认的 Hash 操作会按 int 型的 id 来进⾏分配,这样会导致所有 string 类型 id 的记录都分配到⼀个 Reducer 中。
解决⽅式:把数字类型转换成字符串类型
⼤⼩表的数据倾斜问题
map join
业务数据本⾝特性(存在热点key)
join的每路输⼊都⽐较⼤,且长尾是热点值导致的,可以对热点值和⾮热点值分别进⾏处理,再合并数据
key本⾝不均匀
可以在key上加随机数,或者增加reduce task数量(缩⼩粒度,期望数据变得均匀)
开启数据倾斜时负载均衡:upby.skewindata=true;
思想:先随机分发并处理,在按照key group by来分发处理。
操作:当选项设定为 true,⽣成的查询计划会有两个 MRJob。
第⼀个 MRJob 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 GroupBy Key 有可能被分发到不同的Reduce 中,从⽽达到负载均衡的⽬的;
第⼆个 MRJob 再根据预处理的数据结果按照 GroupBy Key 分布到 Reduce 中(这个过程可以保证相同的原始 GroupBy Key 被分布到同⼀个 Reduce 中),最后完成最终的聚合操作。
控制空值分布
将为空的key转变为字符串加随机数或村随机数,将因空值⽽造成倾斜的数据分布到多个Reduce。
ps:对于;异常值如果不需要的化,最好提前在where条件⼒过滤掉,这样可以式计算量⼤⼤减少
13、hive性能优化常⽤的⽅法
压缩和存储调优泰国需要签证吗
存储格式+压缩算法(parquet/orc+snappy)。(选择那种存储格式还要考虑到cdh和hdp技术栈的⽀持)
1. map阶段输出数据压缩 ,在这个阶段,优先选择⼀个低CPU开销的算法。
2. 对最终输出结果压缩,也可以在hive建表时指定表的⽂件格式和压缩编码
合理利⽤分区分桶西电研究生院
分区是将表的数据在物理上分成不同的⽬录,以便查询时可以精准指定所要读取的分区⽬录,从⽽降低读取的数据量
分桶是将表数据按指定列的hash散列后分在了不同的⽂件中,将来查询时,hive可以根据分桶结构,快速定位到⼀⾏数据所在的分桶⽂件,从⽽提⾼读取效率。
参数调优
// 让可以不⾛mapreduce任务的,就不⾛mapreduce任务
hive>t hive.version=more;
// 开启任务并⾏执⾏
parallel=true;
// 解释:当⼀个sql中有多个job时候,且这多个job之间没有依赖,则可以让顺序执⾏变为并⾏执⾏(⼀般为⽤到union all的时候)
// 同⼀个sql允许并⾏任务的最⼤线程数
parallel.thread.number=8;
// 设置jvm重⽤
// JVM重⽤对hive的性能具有⾮常⼤的影响,特别是对于很难避免⼩⽂件的场景或者task特别多的场景,这类场景⼤多数执⾏时间都很短。jvm的启动过程可能会造成相当⼤的开销,尤其是执⾏的job包含有成千上万个task任务的情况。
t u.jvm.num.tasks=10;
// 合理设置reduce的数⽬
// ⽅法1:调整每个reduce所接受的数据量⼤⼩
educers.ducer=500000000;(500M)
/
/ ⽅法2:直接设置reduce数量
duce.tasks = 20
// map端聚合,降低传给reduce的数据量
t hive.map.aggr=true
// 开启hive内置的数倾优化机制
风长upby.skewindata=true
sql调优
1where条件优化
-- 优化前(关系数据库不⽤考虑会⾃动优化)
lect m.cid,u.id from order m join customer u on( m.cid =u.id )where m.dt='20180808';
-- 优化后(where条件在map端执⾏⽽不是在reduce端执⾏)
lect m.cid,u.id from(lect*from order where dt='20180818') m join customer u on( m.cid =u.id);
2union优化
尽量不要使⽤union(union去掉重复的记录),⽽是使⽤union all,然后再⽤group by去重。
3count distinct优化
count distinct,使⽤⼦查询
lect count(1)from(lect id from tablename group by id) tmp;
将distinct替换成group by实现。
环形排列>nbaol
4⽤in来代替join
如果需要根据⼀个表的字段来约束另⼀个表,尽量⽤in来代替join。in要⽐join快
lect id,name from tb1 a join tb2 b on(a.id = b.id);
lect id,name from tb1 where id in(lect id from tb2);
使⽤in⼦查询
5优化⼦查询
消灭⼦查询内的group by、count(distinct),max,min。可以减少job的数量。
6join优化
reduce join:连接发⽣在reduce阶段,适⽤于⼤表join⼤表。
map join:连接发⽣在map阶段,适⽤于⼤表连接⼩表,⼤表数据从⽂件读取,⼩表数据放在内存中(hive进⾏了优化,⾃动判断⼩表然后进⾏缓存)。
t vert.join=true;
SMB join:sort-merge-bucket join 对⼤表连接⼤表的优化,⽤桶表的概念来进⾏优化。在⼀个桶内发⽣笛卡尔积连接(需要是对两个桶表进⾏join)
t vert.sortmerge.join=true;
t hive.optimize.bucketmapjoin =true;
t hive.optimize.bucketmapjoin.sortedmerge =true;
t vert.ditionaltask=true;
数据倾斜调优
转如何解决数据倾斜问题。
⼩⽂件调优
⼩⽂件的产⽣有三个地⽅,map输⼊,map输出,reduce输出,⼩⽂件过多也会影响hive的分析效率:
设置map输⼊的⼩⽂件合并
串口扩展芯片t mapred.max.split.size=256000000;
//⼀个节点上split的⾄少的⼤⼩(这个值决定了多个DataNode上的⽂件是否需要合并)
t mapred.min.split.de=100000000;
//⼀个交换机下split的⾄少的⼤⼩(这个值决定了多个交换机上的⽂件是否需要合并)
t mapred.min.split.size.per.rack=100000000;去的组词
//执⾏Map前进⾏⼩⽂件合并
t hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;