Hive_ 对比分区,分桶

Hive 动态分区

建表时指出分区字段,但不给值,导入数据时 hive 根据分区字段的值自动创建分区。
开启动态分区需要修改一些配置:
是否开启动态分区,默认:false
set hive.exec.dynamic.partition=true;
动态分区模式,默认:strict:严格模式,至少有一个分区列是静态分区
set hive.exec.dynamic.partition.mode=nostrict;
相关参数:
每一个执行 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;
hive> set hive.exec.dynamic.partition=true;
hive> set hive.exec.dynamic.partition.mode=nostrict;
hive> create table part0 (
id int,
name string
)
PARTITIONED BY (sex string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';
hive> desc part0;
col_name data_type  comment
id int
name string
sex string
# Partition Information
# col_name data_type comment
sex string
导入两个分区的数据
hive> load data local inpath '/root/part0_data' into table part0 PARTITION (sex='1');
hive> load data local inpath '/root/part0_data' into table part0 PARTITION (sex='2');
hive> select * from part0;
part0.id part0.name  part0.sex
1  Jed 1
2  Tom 1
3  Cat 1
1  Jed 2
2  Tom 2
3  Cat 2
创建一个和 part0 表机构完全相同的表 part1
hive> create table part1 like part0;
给 part1 导入数据,使用动态分区
hive> from part0
insert into table part1 partition (sex)
select *;

hive> select * from part1;
part1.id part1.name  part1.sex
1  Jed 1
2  Tom 1
3  Cat 1
1  Jed 2
2  Tom 2
3  Cat 2
使用动态分区导入数据时,不使用 load,因为 load 必须指定分区的值,应该使用
from+select 方式。


Hive 分桶

分桶表是对列值取哈希值的方式,将不同数据放到不同文件中存储。对于 hive 中每一
个表、分区都可以进一步进行分桶。由列的哈希值除以桶的个数来决定每条数据划分在哪
个桶中。比分区更加细粒度。
适用场景:数据抽样( sampling )、map-join
开启分桶支持:
set hive.enforce.bucketing=true;
默认:false。设置为 true 之后,mr 运行时会根据 bucket 的个数自动分配 reduce task
个数。(用户也可以通过 mapred.reduce.tasks 自己设置 reduce 任务个数,但分桶时不推荐
使用)注意:一次作业产生的桶(文件数量)和 reduce task 个数一致。
hive> set hive.enforce.bucketing=true;
创建分桶表
hive> CREATE TABLE bucket(id int, name string, age int)
CLUSTERED BY (age) INTO 4 BUCKETS
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
查看表结构(比 desc table;更详细)
hive> desc formatted bucket;
hive> from bucket_test
insert into table bucket
select *;

hive> select * from bucket;
bucket.id bucket.name bucket.age
1  Tom 11
2  Cat 22
3  Dog 33
4  Tony 44
5  Bob 55
6  Hive 66
7  Hadoop 77
8  Java 88
注意:使用 load 加载数据不会出现分桶的效果
[[email protected] ~]# hdfs dfs -cat /user/hive/warehouse/bucket/000000_0
8,Java,88
4,Tony,44
[[email protected] ~]# hdfs dfs -cat /user/hive/warehouse/bucket/000001_0
7,Hadoop,77
3,Dog,33
抽样查询
TABLESAMPLE 语法:TABLESAMPLE(BUCKET x OUT OF y)
x:表示从哪个 bucket 开始抽取数据
y:必须为该表总 bucket 数的倍数或因子
共抽取(bucketNum/y)个桶的数据,抽取第 x,和第(y+(bucketNum/y))个桶中的数据
例如:
TABLESAMPLE(BUCKET 2 OUT OF 16) 桶总数为 32
共抽取 2(32/16)个桶的数据,抽取第 2(x),和第 18(y+32/16)个桶中的数据
TABLESAMPLE(BUCKET 3 OUT OF 256) 桶总数为 32
共抽取 0.125(32/256)个桶的数据,抽取第 3(x)个桶的 1/8 数据
hive> select id, name, age
from bucket
tablesample(bucket 2 out of 4 on age);#取第二个桶
id  name  age
7  Hadoop 77
3  Dog 33

小结:

分区针对的是数据的存储路径;分桶针对的是数据文件。

分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区,特别是之前所提到过的要确定合适的划分大小这个疑虑。

分桶是将数据集分解成更容易管理的若*分的另一个技术。

 Hive_ 对比分区,分桶