Hive 分区 && 分桶
分区
1. 作用
为什么会有分区?
表的数据量越来越大,hive 在查询时通常会全表扫描,效率低。所以引入分区技术,提高查询的效率;
使用分区列的值作为目录,进行存放数据;这样在存储时,使用分区列进行过滤,只要扫描对应目录下的数据,提高查询的效率。
使用:PARTIONED BY(col_name data_type)
2. 分类
-
静态分区
- 分区列的值,在新增分区和加载分区数据时,必须指定分区名。
-
动态分区
- 分区列的值,非确定,在导入数据的时候自动判断。
动态分区的相关设置:
hive.exec.dynamic.partition=true :是否允许动态分区 hive.exec.dynamic.partition.mode=strict :分区模式设置 strict:最少需要有一个是静态分区 -- 严格模式下会阻止一下操作 为了阻止用户不小心提交恶意hql (1)、对分区表查询,where中过滤字段不是分区字段。 (2)、笛卡尔积join查询,join查询语句,不带on条件 或者 where条件。 (3)、对order by查询,有order by的查询不带limit语句。 nostrict:可以全部是动态分区 hive.exec.max.dynamic.partitions=1000 :允许动态分区的最大数量 hive.exec.max.dynamic.partitions.pernode =100 :单个节点上的mapper/reducer允许创建的最大分区
注意:
- 分区列是一个或者多个伪列,在表的数据文件中并不存储分区列的信息和数据
- 默认模式下,不允许主分区列是动态分区。
分桶
为什么需要分桶?
- 单个分区或者表中的数据量越来越大,当分区不能更细粒的划分数据时,所以会采用分桶技术将数据更细粒度的划分和管理
- 意义:
- 1、为了保存分桶查询结果的分桶结构(数据已经按照分桶字段进行了hash散列)
- 2、分桶表数据进行抽样和JOIN时可以提高MR程序效率
1. 原理
分桶则是指定分桶表的某一列,让该列数据按照 哈希取模 的方式随机、均匀地分发到各个桶文件中。因为分桶操作需要根据某一列具体数据来进行哈希取模操作,故指定的分桶列必须基于表中的某一列(字段)。因为分桶改变了数据的存储方式,它会把哈希取模相同或者在某一区间的数据行放在同一个桶文件中。如此一来便可提高查询效率,如:我们要对两张在同一列上进行了分桶操作的表进行JOIN操作的时候,只需要对保存相同列值的桶进行JOIN操作即可。同时分桶也能让取样(Sampling)更高效。
2. 作用
-
方便抽样
-
提高 join 查询效率
-
分桶数据的导入
-
先创建一个分桶的空表
-
再建立一个临时表 将数据添加到临时表内
-
通过查询 insert 将数据导入到分桶表中
方法一:打开enforce bucketing开关。
SET hive.enforce.bucketing=true; ①
INSERT (INTO|OVERWRITE) TABLE <bucketed_table> SELECT <select_statement>
[SORT BY <sort_key> [ASC|DESC], [<sort_key> [ASC|DESC], …]]; ②insert overwrite table buc3 select uid,uname,uage from buc_temp cluster by (uid); insert overwrite table buc3 select uid,uname,uage from buc_temp distribute by (uid) sort by (uid asc); insert overwrite table buc3 select uid,uname,uage from buc_temp distribute by (uid) sort by (uid desc); insert overwrite table buc3 select uid,uname,uage from buc_temp distribute by (uid) sort by (uage desc);
方法二:将reducer个数设置为目标表的桶数,并在 SELECT 语句中用 DISTRIBUTE BY <bucket_key>对查询结果按目标表的分桶键分进reducer中。
-
总结
-
定义:
clustered by (uid) – 指定分桶的字段
sorted by (uid desc) – 指定数据的排序规则,表示预期的数据就是以这里设置的字段以及排序规则来进行存储 -
导数据
cluster by (uid) – 指定getPartition以哪个字段来进行hash散列,并且排序字段也是指定的字段,默认以正序进行排序distribute by(uid) – 指定getPartition以哪个字段来进行hash散列
sort by(uid asc) – 指定排序字段,以及排序规则
–更灵活的方式,这种数据获取方式可以分别指定getPartition的字段和sort的字段cluster by (uid)与distribute by(uid) sort by (uid asc)结果是一样的so
-
order by && sorted by
- sorted by 局部排序,保证每个reduce上有序,如果只有一个 reduce,那么和order by 一样
- order by 是全局排序,只有一个 reduce,如果数据量大的话,那么 reduce 就成为了单点,速度很慢
-
distribute by与group by 的区别
- 都是按key值划分数据 都使用reduce操作唯一不同的是,distribute by只是单纯的分散数据,distribute by col – 按照col列把数据分散到不同的reduce。而group by把相同key的数据聚集到一起,后续必须是聚合操作。
-
-