order by
需要reduce操作,且 只有一个reduce,与配置无关。 数据量很大时,慎用。
group by
使用了reduce操作, 受限于reduce数量,设置reduce参数 mapred.reduce.tasks
输出文件个数与reduce数相同
数据倾斜,优化参数 hive.groupby.skewindata为true,会启动一个优化程序,避免数据倾斜。
left semi join
类似 exists。即查找a表中的数据, 是否在b表中存在,找出存在的数据。
mapjoin
在map端完成join操作,不需要用reduce,基于内存做join,属于优化操作,其中使用了分布式缓存技术。
mapjoin顾名思义,就是在map端完成join操作,把小数据集分发到map的每台机器上去做join,避免shuffle操作
distribute by与group by对比
都是按key值划分数据
都使用reduce操作
**唯一不同的是**distribute by只是单纯的分散数据,而group by把相同key的数据聚集到一起,后续必须是聚合操作。
distribute by也是存在数据倾斜问题的,热点key会被分布到个别reduce节点上
order by与sort by 对比
order by是全局排序
sort by只是确保每个reduce上面输出的数据有序。如果只有一个reduce时,和order by作用一样。
cluster by
把有相同值的数据聚集到一起,并排序。
效果等价于distribute by col sort by col
cluster by col <==> distribute by col sort by col
union all
多个表的数据合并成一个表,hive不支持union
是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,
而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。
而且,同时可执行的map数是受限的。
1.Hive自己如何确定reduce数:
reduce个数的设定极大影响任务执行效率,不指定reduce个数的情况下,Hive会猜测确定一个reduce个数,基于以下两个设定:
hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,默认为1000^3=1G)
hive.exec.reducers.max(每个任务最大的reduce数,默认为999)
计算reducer数的公式很简单N=min(参数2,总输入数据量/参数1)
即,如果reduce的输入(map的输出)总大小不超过1G,那么只会有一个reduce任务;
如:select pt,count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04' group by pt;
总大小为9G多,因此这句有10个reduce
2.调整reduce个数方法一:
调整hive.exec.reducers.bytes.per.reducer参数的值;
set hive.exec.reducers.bytes.per.reducer=500000000; (500M)
这次有20个reduce
3.调整reduce个数方法二;
set mapred.reduce.tasks = 15;
这次有15个reduce
4.reduce个数并不是越多越好;
同map一样,启动和初始化reduce也会消耗时间和资源;
另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
5.什么情况下只有一个reduce;
很多时候你会发现任务中不管数据量多大,不管你有没有设置调整reduce个数的参数,任务中一直都只有一个reduce任务;
其实只有一个reduce任务的情况,除了数据量小于hive.exec.reducers.bytes.per.reducer参数值的情况外,还有以下原因:
a)没有group by的汇总,比如把select pt,count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04' group by pt;
写成 select count(1) from popt_tbaccountcopy_mes where pt = '2012-07-04';
这点非常常见,希望大家尽量改写。
b)用了order by,全局排序
c)有笛卡尔积
通常这些情况下,除了找办法来变通和避免,我暂时没有什么好的办法,因为这些操作都是全局的,所以hadoop不得不用一个reduce去完成;
同样的,在设置reduce个数的时候也需要考虑这两个原则:使大数据量利用合适的reduce数;使单个reduce任务处理合适的数据量;
3.怎样写exist/in子句?
Hive不支持where子句中的子查询,SQL常用的exist in子句需要改写。这一改写相对简单。考虑以下SQL查询语句:
SELECT a.key, a.value FROM a WHERE a.key in (SELECT b.key FROM B);
可以改写为
SELECT a.key, a.value FROM a LEFT OUTER JOIN b ON (a.key = b.key) WHERE b.key <> NULL;
一个更高效的实现是利用left semi join改写为:
SELECT a.key, a.val FROM a LEFT SEMI JOIN b on (a.key = b.key);
1、如何合并小文件,减少map数?
如果一个表中的map数特别多,可能是由于文件个数特别多,而且文件特别小照成的,可以进行如下操作,合并文件,:
set mapred.max.split.size=100000000; // 100M
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; // 合并小文件
2、如何适当的增加map数?distribute by
如果表A只有一个文件,大小为120M,包含几千万记录,可以考虑用多个map任务完成
set mapred.reduce.tasks=10;
create table a_1 as
select * from a
distribute by rand(123); //将a表的记录,随机的分散到包含10个文件的a_1表中
3.如果设计和使用bucket
所用场合:对某一列进行分区,比如对用户ID进行分区,例如:
CREATE TABLE weblog (user_id INT, url STRING, source_ip STRING)
PARTITIONED BY (dt STRING)
CLUSTERED BY (user_id) INTO 96 BUCKETS; // 按照日期分区后,再按照user_id把日志放在96个篮子里。
4.count(distinct)
当count distinct 的记录非常多的时候,设置以下两个参数:
hive> hive.map.aggr = true — 在map端进行combine
hive> set hive.groupby.skewindata=true;
hive> select count (distinct gid) from cookie_label_summary where i_date=20130924;
5.group by
map端聚合,提前一部分计算:hive.map.aggr = true 同时设置间隔:hive.groupby.mapaggr.checkinterval
均衡处理:hive.groupby.skewindata
这是针对数据倾斜的,设为ture的时候,任务的reduce会把原来一个job拆分成两个,第一个的job中reduce处理处理不同的随即分发过来的key的数据,生成中间结果,再由最后一个综合处理。
(解决group by的数据倾斜主流就是设置这个参数,相当于先用一组随机key先汇总一次,然后去掉随机数继续汇总,注意这个参数是专门为group by设计的)
6.order by, sort by ,distribute by, cluster by
order by VS Sort by:
order by是在全局的排序,只用一个reduce去跑,所以在set hive.mapred.mode=strict 模式下,order by 必须limit,否则报错。Sort by只保证同一个reduce下排序正确。
Distribute by with sort by:
Distribute by 是按指定的列把map 输出结果分配到reduce里(经常用来增加map数)。所以经常和sort by 来实现对某一字段的相同值分配到同一个reduce排序。
Cluster by 实现了Distribute by+ sort by 的功能
先cluser by,最后再order by,真的会提供整体排序效率吗?
未实验验证,从原来上看是的,先在map端局部排序
所以面试官问order by造成的数据倾斜如何解决时,应该就是要回答这一点,先distribute在map端就把数据倾斜解决掉,然后map端排序