Hive的优化

Hive的优化

1. 查询join的优化

1. 尽量不使用子查询、尽量不使用in 或者not in (可以使用 [not] exists替代)
2. 尽量避免join连接查询,但是通常避免不了
3. 查询永远是小表驱动大表(小表作为驱动表)
  --注意:内连接时,默认是左表是驱动表,因此左表一定要是小表。
  --	 外连接看需求而定。  

2. 半开连接

在hive中,有一种专有的join操作,left semi join,我们称之为半开连接。它是left join的一种优化形式,只能查询左表的信息,主要用于解决hive中左表的数据是否存在的问题。
-- (注意右表的字段只能在on子句中引用,而不能在其他的地方引用,包括select,where子句中)


select distinct * from student left semi join score on (score.s_id=student.s_id and score.c_id='01');

select distinct * from student
where exists (
select 1 from score where score.s_id=student.s_id and score.c_id='01'
)

-- 2.半开连接功能更加全,可以适应更多场景(可以比in/exists子查询更高效的实现功能)
-- 例如:对于以下的例子hive中的where子查询是不支持的(不是不支持where中的子查询,而是不支持这种非等值的where子查询)

select stu1.s_name,count(1)
from student stu1
where exists(
select 1 from student stu2 
where stu1.s_name=stu2.s_name and stu1.s_id!=stu2.s_id
)
group by stu1.s_name;

-- 而对于left semi join可以(但是是对2.2.0版本而言)
select stu1.s_name,count(1)
from student stu1 left semi join student stu2 on (stu1.s_name=stu2.s_name and stu1.s_id!=stu2.s_id) 
group by stu1.s_name;

关于join中的on子句的官方文档说明,在hive2.2后on子句才是可以在on子句中实现更为复杂的表达式,如:不等值表达式(!=,<>,>)等
关于hive中的join的on子句
hive中在0.13版本后就支持某些where的子查询,但是where子查询中只支持(not)in或exists的子查询(在(not)in/exists子句中将子查询的结果作为常量)。同时由于hive中对子查询的支持度较低,有如下官方文档限制:
关于hive中的子查询的官方介绍

3. map-side join

map-side join:正如这名字一样,在map端就join连接,从而减少了不必要的数据从map端shuffle到reducer端,从而提高了效率,减少网络io的占用。
-- 但是这种情况使用于小表和大表进行join的时候。
实现:先在setup方法(mapTask任务开始前会调用一次)中,通过分片信息找到小表,把小表的数据加载到内存中(Map,List)。然后再和map方法读取的大表的信息进行join.过滤掉不要的数据,从而提高查询效率。

4. count的优化

count的执行
1. 执行效果上:
	- count(*)包括了所有的列,相当于行数,在统计结果的时候不会忽略null- count(1)包括了所有列,用1代表行,在统计结果的时候也不会忽略null- count(列名)只包括列名那一列,在统计结果时,会忽略null2.执行效率上:
	- 列名为主键,count(列名)会比count(1)- 列名不为主键,count(1)会比count(列名)- 如果表中有多个列并且没有主键,count(1)的效率高于count(*)
	- 如果有主键count(主键)效率是最高的
	- 如果表中只有一个字段count(*)效率最高
	

5. 分区与分桶

--分区
随着系统运行时间越来越长,表的数据量越来越大,而hive查询如果还是通过全表查询来进行查询,效率是极低的。而且我们所需查询的数据是从特定的一部分数据查询即可,从而引出了分区partition的概念。即在建表时,将整个存储在不同子目录中,每个目录对应一个分区。查询时,我们就可以指定分区查询,避免了hive做全表扫描,提高效率。

分区的类型:
1. 静态分区:直接加载数据文件到指定分区
2. 动态分区:数据未知,根据分区值来确定需要创建的分区(加载数据insert into模式)
3. 混合分区:静态和动态都有

注意事项:
1.hive的分区使用的是表外字段,分区字段是一个伪例,并不一定来源与原数据内。但是分区字段可以做查询过滤。
2.一般不建议使用动态分区,因为动态分区会使用MapReduce进行查询数据,如果分区数据过多,导致namenode和resourcemanager的性能瓶颈。所以建议在使用动态分区前尽可能预知分区数量。


-- 分桶
与MapReduce中的HashPartitioner的原理一模一样
其实简单来说就是,将数据平均的分在不同的“桶”里。分配规则是使用分桶字段的hash值对分桶的数量进行取模,通过分析余数来确定放入哪个桶中

分桶的主要意义:分桶表主要适合进行'数据的抽样'
注意:加载数据时:绝对不能使用load或者上传方式,而是需要类似与动态分区一样加载数据

如有问题欢迎及时提醒,一起讨论与学习!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值