Hive的分区与分桶

Hive的分区与分桶

Hive的分区

分区的代码标准格式:
通过建表时就定义分区(用PARTITIONED BY定义分区)

CREATE TABLE employee_partitioned(
    name string,
    work_place ARRAY<string>,
    sex_age STRUCT<sex:string,age:int>,
    skills_score MAP<string,int>,
    depart_title MAP<STRING,ARRAY<STRING>> )
PARTITIONED BY (year INT, month INT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '|'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';

分区的作用

主要用于提高性能
分区列的值将表划分为segments(文件夹)
查询时使用“分区”列和常规列类似
查询时Hive自动过滤掉不用于提高性能的分区
分为静态分区和动态分区

静态分区

ALTER TABLE的方式添加静态分区
ADD添加分区, DROP删除分区

ALTER TABLE employee_partitioned ADD 
PARTITION (year=2019,month=3) PARTITION (year=2019,month=4); 
ALTER TABLE employee_partitioned DROP PARTITION (year=2019, month=4);

动态分区

使用动态分区需要先设定属性

set hive.exec.dynamic.partition=true;              --允许动态分区
set hive.exec.dynamic.partition.mode=nonstrict;     --关闭严格模式
set hive.mapred.mode=nonstrict;                    --关闭mapreduce的严格模式
set yarn.scheduler.minimum-allocation-mb=1024      --虚拟内存值,可以根据实际情况调整
set hive.exec.max.dynamic.partitions.pernode=20000;  -- 允许的最大分区数,默认是100

insert方式添加动态分区

insert into table employee_partitioned partition(year, month)
select name,array('Toronto') as work_place,
named_struct("sex","male","age",30) as sex_age,
map("python",90) as skills_score,
map("r&d", array('developer')) as depart_title,
year(start_date) as year,month(start_date) as month
from employee_hr eh ;	

Hive的分桶

分桶的作用

更高的查询处理效率

使抽样(sampling)更高效

根据“桶列”的哈希函数将数据进行分桶

分桶只有动态分桶

扫描二维码关注公众号,回复: 13041259 查看本文章

分桶的定义

分桶的列是表中已有的列
分桶数最好是2的n次方
必须使用INSERT方式加载数据

CLUSTERED BY (employee_id) INTO 2 BUCKETS

分桶的抽样

可以基于整行数据进行随机抽样

SELECT * FROM table_name TABLESAMPLE(BUCKET 3 OUT OF 32 ON rand()) s;  
 --抽取32份中的第3份桶的随机数据

可以基于指定列进行随机抽样(使用分桶列更高效)

SELECT * FROM table_name TABLESAMPLE(BUCKET 3 OUT OF 32 ON id) s;
--抽取32份中第3份桶的桶分列id 的数据

也可以基于block size进行随机抽样

SELECT * FROM table_name TABLESAMPLE(10 PERCENT) s;   --抽取10%的数据进行展示
SELECT * FROM table_name TABLESAMPLE(1M) s;           --抽取1M大小的文件内容进行展示
SELECT * FROM table_name TABLESAMPLE(10 rows) s;      --抽取前10行数据进行展示

总结

分区

Hive的分区使用HDFS的子目录功能实现。每一个子目录包含了分区对应的列名和每一列的值。但是由于HDFS并不支持大量的子目录,这也给分区的使用带来了限制。我们有必要对表中的分区数量进行预估,从而避免因为分区数量过大带来一系列问题。
Hive查询通常使用分区的列作为查询条件。这样的做法可以指定MapReduce任务在HDFS中指定的子目录下完成扫描的工作。HDFS的文件目录结构可以像索引一样高效利用。

分桶

分桶是指定分桶表的某一列,让该列数据按照哈希取模的方式随机、均匀的分发到各个桶文件中。因为分桶操作需要根据某一列具体数据来进行哈希取模操作,故指定的分桶列必须基于表中的某一列(字段)。分桶改变了数据的存储方式,它会把哈希取模相同或者在某一个区间的数据行放在同一个桶文件中。如此一来便可以提高查询效率。如果我们需要对两张在同一个列上进行了分桶操作的表进行JOIN操作的时候,只需要对保存相同列值的通进行JOIN操作即可。

还有一点需要点一下:在hive中的数据是存储在hdfs中的,我们知道hdfs中的数据是不允许修改只能追加的,那么在hive中执行数据修改的命令时,就只能先找到对应的文件,读取后执行修改操作,然后重新写一份文件。如果文件比较大,就需要大量的IO读写。在hive中采用了分桶的策略,只需要找到文件存放对应的桶,然后读取再修改写入即可。

抽样语句 tablesample(bucket x out of y)

tablesample是抽样语句

tablesample(bucket x out of y)

y必须是table总共bucket数的倍数或者因子。Hive根据y的大小,决定抽样的比例。

例如:table总共分了64份,当y=32时,抽取2(64/32)个bucket的数据,当y=128时,抽取1/2(64/128)个bucket的数据。x表示从哪个bucket开始抽取。

例如:table总共bucket数为32,tablesample(bucket 3 out of 16)表示总共抽取2(32/16)个bucket的数据,分别为第三个bucket和第19(3+16)个bucket的数据。

今天的分享就到这里,谢谢!

猜你喜欢

转载自blog.csdn.net/giantleech/article/details/115330440
今日推荐