Hive动态分区、分桶、视图、join操作

Hive动态分区、分桶、视图、join操作

Hive的动态分区、分桶采用了分而治之的思想,显著提高了数据的查询效率。视图与查询结合起来,提升了hql语句的可读性。Hive执行引擎会将HQL“翻译”成为MapReduce任务,如果多张表使用同一列做Join,将被“翻译”成一个MapReduce任务,这样就大大减少了MapReduce的作业量。下面进行详细介绍。

1. Hive动态分区

1.1 hive的动态分区介绍

​ hive的静态分区需要用户在插入数据的时候必须手动指定hive的分区字段值,但是这样的话会导致用户的操作复杂度提高,而且在使用的时候会导致数据只能插入到某一个指定分区,无法让数据散列分布,因此更好的方式是当数据在进行插入的时候,根据数据的某一个字段或某几个字段值动态的将数据插入到不同的目录中,此时,引入动态分区。

1.2 hive的动态分区配置
--hive设置hive动态分区开启
	set hive.exec.dynamic.partition=true;
	默认:true
--hive的动态分区模式
	set hive.exec.dynamic.partition.mode=nostrict;
	默认:strict(至少有一个分区列是静态分区)
--每一个执行mr节点上,允许创建的动态分区的最大数量(100)
	set hive.exec.max.dynamic.partitions.pernode;
--所有执行mr节点上,允许创建的所有动态分区的最大数量(1000)	
	set hive.exec.max.dynamic.partitions;
--所有的mr job允许创建的文件的最大数量(100000)	
	set hive.exec.max.created.files;
1.3 hive动态分区语法
--Hive extension (dynamic partition inserts):
	INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) 		select_statement FROM from_statement;
	INSERT INTO TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) 			select_statement FROM from_statement;

:这里介绍的是Hive的动态分区,分区介绍可以参考Hive 基础数据结构和基本语法DDL详解的分区部分。

2、Hive分桶

2.1 Hive分桶的介绍
	Bucketed tables are fantastic in that they allow much more efficient sampling than do non-bucketed tables, and they may later allow for time saving operations such as mapside joins. However, the bucketing specified at table creation is not enforced when the table is written to, and so it is possible for the table's metadata to advertise properties which are not upheld by the table's actual layout. This should obviously be avoided. Here's how to do it right.

​ 注意:

​ 1、Hive分桶表是对列值取hash值得方式,将不同数据放到不同文件中存储

​ 2、对于hive中每一个表、分区都可以进一步进行分桶

​ 3、由列的hash值除以桶的个数来决定每条数据划分在哪个桶中

2.2 Hive分桶的配置
--设置hive支持分桶
	set hive.enforce.bucketing=true;
2.3 Hive分桶的抽样查询
--案例
	select * from bucket_table tablesample(bucket 1 out of 4 on columns)
--TABLESAMPLE语法:
	TABLESAMPLE(BUCKET x OUT OF y)
		x:表示从哪个bucket开始抽取数据
		y:必须为该表总bucket数的倍数或因子
取样数量为桶的数量除以y:num/y
例如有4个桶,x = 2, y=8,则取4/8 = 1/2个桶数据,就是从第二个桶开始,取二分之一个桶的数据,假设第二个桶有4条数据,二分之一个桶就是2条,
也就是说会取第二个桶的前两条数据。

3.分区和分桶的区别

分区和分桶本质上都是为了提高Hive的查询效率,它们都是采取了分而治之的思想,目的相同,但是实现方式不同。主要集中在以下几点:

3.1 划分方式不同
  • 分区使用分区列的value进行划分,每一个value对应一个分区;分桶的数量由用户指定,根据分桶列的进行hash(),然后对分桶数量取模得到桶号。
  • 分区使用HDFS的子目录功能实现。每一个子目录包含了分区对应的列名和每一列的值,Hive的一个分区名对应一个目录名,子分区名就是子目录名,并不是一个实际字段。注意:partitned by子句中定义的列是表中正式的列(分区列),但是数据文件内并不包含这些列。分桶是在表或者分区的基础上,进一步对表进行组织,保证了每个桶中都有数据,但每个桶中的数据条数不一定相等。
3.2 划分粒度不同
  • 分桶随机分割数据库,分区是非随机分割数据库。因为分桶是按照列的哈希函数进行分割的,相对比较平均;而分区是按照列的值来进行分割的,容易造成数据倾斜。
  • 分桶是对应不同的文件(细粒度),分区是对应不同的文件夹(粗粒度)。桶是更为细粒度的数据范围划分,分桶的比分区获得更高的查询处理效率,使取样更高效。
3.3 优化方式不同
  • 分区使得Hive进行查询操作时,只需取指定部分的数据,而不用全量拉取,这样进入MapReduce阶段的数据量就少了,从而减少了查询时间。
  • 分桶实际上是提前做好了map阶段需要做的HashPartition,使得map shuffle的工作量变小了,从而减少了查询的时间。

4.视图

4.1 Hive视图基本介绍

​ Hive 中的视图和RDBMS中视图的概念一致,都是一组数据的逻辑表示,本质上就是一条SELECT语句的结果集。视图是纯粹的逻辑对象,没有关联的存储(Hive 3.0.0引入的物化视图除外),当查询引用视图时,Hive可以将视图的定义与查询结合起来,例如将查询中的过滤器推送到视图中。

4.2 Hive视图特点

​ 1、不支持物化视图
​ 2、只能查询,不能做加载数据操作
​ 3、视图的创建,只是保存一份元数据,查询视图时才执行对应的子查询
​ 4、view定义中若包含了ORDER BY/LIMIT语句,当查询视图时也进行ORDER BY/LIMIT语句操作,view当中定义的优先级更高
​ 5、view支持迭代视图

4.3 Hive视图语法
--创建视图:
	CREATE VIEW [IF NOT EXISTS] [db_name.]view_name 
	  [(column_name [COMMENT column_comment], ...) ]
	  [COMMENT view_comment]
	  [TBLPROPERTIES (property_name = property_value, ...)]
	  AS SELECT ... ;
--查询视图:
	select colums from view;
--删除视图:
	DROP VIEW [IF EXISTS] [db_name.]view_name;

5. Join

5.1 Join基本介绍

Join是从多个数据表中读取数据并进行关联查询的操作。Hive中除了支持和传统数据库中一样的内关联、左关联、右关联、全关联,还支持LEFT SEMI JOIN和CROSS JOIN,但这两种JOIN类型也可以用前面的代替。

为了演示Join操作之间的关系以及使用注意事项,准备如下三个表。

-- 表1:CREATE TABLE `FDM_SOR.mytest_department`(

`dept_no` int,

`dept_name` string) row format delimited fields terminated by ','

 

-- 表2:CREATE TABLE `FDM_SOR.mytest_staffinfo`(

`id` int,

`name` string,

sex string,

dept_no int

)row format delimited fields terminated by ','

 

-- 表3:CREATE TABLE `FDM_SOR.mytest_deptaddr`(

     `dept_no` int,

    `addr` string,

    `tel` string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
5.2 Inner Join
--inner join(内连接,只有进行连接的两个表中都存在与连接条件相匹配的数据才会被留下来) 
select a.id ,a.name,b.dept_no,b.dept_name from FDM_SOR.mytest_staffinfo a

inner join

FDM_SOR.mytest_department b

on a.dept_no = b.dept_no
5.3 Left Join
--left join 是左外连接(Left Outer Jion),其中outer可以省略,left outer join是早期的写法
--左表(A)的记录将会全部表示出来(不管右边的表中是否存在与它们匹配的行),而右表(B)只会显示符合搜索条件的记录,比如符合on,where中的条件。
--B表记录不足的地方均为NULL.   A  left   join   B   等价B   right   join   A  
select a.id ,a.name,b.dept_no,b.dept_name

from FDM_SOR.mytest_staffinfo a left join FDM_SOR.mytest_department b

on a.dept_no = b.dept_no
5.4 Right Join
--right join ,同理和left join相反,A right join B ,则显示B表中所有的记录,A表不足的用null填充
select a.id ,a.name,b.dept_no,b.dept_name

from FDM_SOR.mytest_staffinfo a right outer join FDM_SOR.mytest_department b

on a.dept_no = b.dept_no
5.5 Full Join
--包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行
--在功能上,它等价于对这两个数据集合分别进行左外连接和右外连接,然后再使用消去重复行的并操作将上述两个结果集合并为一个结果集。
select a.id ,a.name,b.dept_no,b.dept_name

from FDM_SOR.mytest_staffinfo a full join FDM_SOR.mytest_department b

on a.dept_no = b.dept_no

order by a.id
5.6 Left Semi Join
--left semi join  左半开连接 ,会显示左半边表中记录,前提是其记录对于右半边表满足于on语句中判定条件。
select a.id ,a.name,a.dept_no

from FDM_SOR.mytest_staffinfo a

where a.dept_no in (

select dept_no from FDM_SOR.mytest_department

where dept_no > 102

)
5.7 Map端Join
-- 假如JOIN两张表,其中有一张表特别小(可以放在内存中),可以使用Map-side JOIN。
-- Map-Side JOIN是在Mapper中做JOIN,原理是将其中一张JOIN表放到每个Mapper任务的内存中,从而不用Reduce任务,在Mapper中就完成JOIN。
SELECT MAPJOIN(b) a.id,a.dept_no from FDM_SOR.mytest_staffinfo a 

join FDM_SOR.mytest_department b 

on a.id = b.id;

参考资料:

https://blog.csdn.net/weixin_39393048/article/details/82530254
https://blog.csdn.net/leying521/article/details/93197951
https://www.jianshu.com/p/ae9b952abf6e

发布了17 篇原创文章 · 获赞 0 · 访问量 336

猜你喜欢

转载自blog.csdn.net/qq_37163925/article/details/105724840