1、Fetch 抓取
Fetch 抓取是指,Hive 中对某些情况的查询可以不必使用 MapReduce 计算。
例如: SELECT * FROM employees;在这种情况下,Hive 可以简单地读取employee 对应的存储目录下的文件,然后输出查询结果到控制台。
在 hive-default.xml.template 文件中 hive.fetch.task.conversion 默认是 more,老版本 hive 默认是 minimal,该属性修改为 more 以后,在全局查找、字段查找、limit 查找等都不走mapreduce。
把 hive.fetch.task.conversion 设置成 none,然后执行查询语句,都会执行 mapreduce程序。
把 hive.fetch.task.conversion 设置成 more,然后执行查询语句,
如下查询方式都不会执行 mapreduce 程序
2、本地模式
set hive.exec.mode.local.auto=true //开启本地模式
要求:默认数据小于128M,默认文件个数小于4,超过则会自动转换为Hadoop模式。也可以自行修改
数据和文件限制。
3、Join表的优化
空key过滤
insert overwrite table jointable
select n.* from nullidtable n left join ori o on n.id = o.id;
insert overwrite table jointable
select n.* from (select * from nullidtable where id is not null ) n //过滤空Key
left join ori o on n.id = o.id;
空Key转换
空key会集中到一个Reduce中,导致数据倾斜
insert overwrite table jointable
select n.* from nullidtable n left join ori b on n.id = b.id;
insert overwrite table jointable
select n.* from
nullidtable n full join
ori o
on
case when n.id is null then concat('hive', rand()) else n.id end //如果o.id为null则分配一个随机数
= o.id;
总体时间会加长,但解决了数据倾斜的问题,保证MR能正常运行
Map Join
set hive.auto.convert.join = true; 默认为 true
大表小表的阈值设置(默认 25M 一下认为是小表):
set hive.mapjoin.smalltable.filesize=25000000; //可调高阈值来缩短时间
如果不指定 MapJoin 或者不符合 MapJoin 的条件,那么Hive 解析器会将Join 操作转换成 Common Join,即:在 Reduce 阶段完成 join。
容易发生数据倾斜。可以用 MapJoin 把小表全部加载到内存在 map 端进行 join,避免 reducer 处理。
4、Group By
默认情况下,Map 阶段同一 Key 数据分发给一个 reduce,当一个 key 数据过大时就倾斜了
并不是所有的聚合操作都需要在 Reduce 端完成,很多聚合操作都可以先在 Map 端进行部分聚合,最后在Reduce 端得出最终结果
hive.map.aggr = true //是否在 Map 端进行聚合,默认为True
hive.groupby.mapaggr.checkinterval = 100000 //在 Map 端进行聚合操作的条目数目
hive.groupby.skewindata = true //有数据倾斜的时候进行负载均衡(默认是 false)
当选项设定为 true,生成的查询计划会有两个MR Job。
第一个MR Job 中,Map 的输出结果会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的Reduce 中,从而达到负载均衡的目的;
第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中
(这个过程可以保证相同的Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作
5、去重统计
COUNT DISTINCT (去重统计)使用先 GROUP BY 再 COUNT 的方式替换
select count(distinct id) from bigtable;
select count(id) from (select id from bigtable group by id) a;
6、行列过滤
列处理:在 SELECT 中,只拿需要的列,如果有,尽量使用分区过滤,*不要用 SELECT ,要用的话加上limit
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在 Where 后面,那么就会先全表关联,之后再过滤
7、动态分区
插入数据时,按字段分区【PARTITIONED BY (p_time)】
set hive.exec.dynamic.partition=true //开启动态分区功能(默认 true,开启)
set hive.exec.dynamic.partition.mode=nonstrict //设置为非严格模式
set hive.exec.max.dynamic.partitions=1000 //在所有执行 MR 的节点上,最大一共可以创建多少个动态分区
set hive.exec.max.dynamic.partitions.pernode=100 //节点的动态分区
insert into table dept_par partition(deptno)
select deptno,dname,loc from dept; //发现会按照loc来分区,所以动态分区一定要把分区字段写在最后
8、MR优化
合理设置 Map 数
小文件进行合并
复杂文件增加 适量的Map 数
合理设置 Reduce 数
说的都是P话。。。。
9、并行执行
set hive.exec.parallel=true; //打开任务并行执行
set hive.exec.parallel.thread.number=16; ////同一个 sql 允许最大并行度,默认为 8。
意思是,一堆任务执行时,某一个任务执行得很慢,系统就会再启动一个任务同时执行,先执行完的可以kill慢的进程。
10、严格模式
根据参数得
Cartesian Product. //限制笛卡尔积
No partition being picked up for a query. //除非 where 语句中含有分区字段过滤条件来限制范围,否则不允许执行
Comparing bigints and strings.
Comparing bigints and doubles.
Orderby without limit. //order by必须加limit