Hive(二)--分区分桶,内部表外部表

版权声明:原创作品转载必须标明出处,谢谢配合! https://blog.csdn.net/qq_38704184/article/details/84590478

1.简述

Hive是hadoop生态圈中实现数据仓库的一项技术。虽然hadoop和hdfs的设计局限了Hive所能胜任的工作,但是hive仍然是目前互联网中最适合数据苍鹭的应用技术。不论从“品相还是举止”,hive都像一个关系型数据库。用户对数据库、表和列这类术语比较熟悉的话,那么掌握hive的查询语言HQL也轻而易举。不过,hive的实现和使用方式与传统的关系数据库相比,有很多不同的地方。

2.内部表与外部表

hive将数据表分为内部表和外部表。

内部表

在hive中穿点的普通的表都可以称为“内部表”。因为hive可以(或多或少)控制其数据的生命周期,内部表对数据拥有所有权。比如我们常见的,通常hive会将内部表数据储存在有hive.metastore.warehouse.dir所定义的目录下。

所以,当删除一个内部表时,相应的数据也会被删除。

外部表

内部表不方便共享数据源。例如,当采用如Pig或MapReduce等李树工具数据处理时,我们将无法读取内部表的数据,也不能将外部数据直接作为内部表数据源分享给hive。这样的需求就诞生了外部表。不同于内部表,hive对外部表的数据仅仅拥有使用权,而数据位置可有表管理者任意配置。

如图所示:外部表不需要将数据复制到hive中,一旦关联数据格式和数据位置,hive就能直接访问外部数据,非常灵活方便,即插即用。

而加载内部表数据时,hive会自动将数据源拷贝到内部。内部表其实访问的是数据副本。

注意:hive架子啊内部表数据后会把源数据删除,很像“剪切/移动”,所以,忘内部表上传数据时,千万记得备份数据!

3.分区和分桶分区

对于大型数据处理系统而言,数据分区的功能非常重要的。因为hive通常要对数据进行全盘扫描,才能满足查询条件。

以hive管理大型网站的浏览日志为例。如果日志数据不采用分区实际,那么就单日网站流量分析这样的需求而言,hive就必然要通过遍历全量日志来完成查询。以一年日志为全量,单日查询的数据利用率将不到1%,这样的设计基本上将查询的时间浪费在了数据加载上。分区的优势在于利用唯独分割数据。在使用分区维度查询时,hive只需要加载数据,极大缩短数据加载时间。

由于HDFS被设计用于存储大型数据文件而非海量碎片文件,理想的分区方案不应该导致过多的分区文件,并且每个目录下的文件尽量超过HDFS块大小的若干倍。按天级时间粒度进行分区就是一个号的分区策略,随时间的推移,分区数量增长均可控。此外常有的分区策略还有地域,语言种类等等。设计分区的时候,还有一个误区要避免。关于分区维度的选择,我们应该尽量选择那些有限且少量的数据集作为分区,例如国家、省份就是一个良好的分区,而城市就可能不适合进行分区。

注意:分区是数据表的一个列名,但是这个列名并不占有表的实际存储空间。他作为一个虚拟列为存在。

分区提供了一种整理数据和优化查询的遍历方式。不过,并非所有数据集都可形成合力的分区,特别是在需要合力划分数据、防止倾斜时。分桶是将数据分解管理的另一种技术。

分桶解决的是数据倾斜的问题。因为痛的数据固定,所以没有数据波动。桶对于数据抽样在适合不过,同时也有利于高效的map-side Join。

分桶与分区的关系:

  1. 分区和分桶都可以单独于表
  2. 分区可以是多级
  3. 分区和分桶可以嵌套使用,但是分区必须在分桶前面

分区表:

  1. 一个表可以拥有一个或多个分区,每个分区以文件夹的形式单独存在于表文件夹的目录下
  2. 表和列名不区分大小写
  3. 分区是以字段的形式在表结构中存在,通过desc table tablename命令可以查看到字段的存在,但是该字段不存放实际的数据内容,仅仅是分区的标识(伪列)

语法:1.创建一个分区表

create table t_hive_partition(id int,name string) partitioned by (ds string) row format delimited fields terminated by '\t' stored as textfile

2.将数据添加到时间为xxxx这个分区中

load data local inpath '/root/hive_partition.data' overwrite into table t_hive_partition pasrtition(ds = '2018-11-28');

3.从一个分区表中查询数据:

select * from t_hive_partition where ds = '2018-11-28';

4.查看具体的分区情况

show partitions tablename;

分桶分区:

对于每一个表或者分区,hive可以进一步组织成桶,也就是说是更为细粒度的数据范围划分。hive也是针对某一行进行桶的组织。hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在呢个桶里面。

比如现在有这样的数据:我们分四个桶

1  张三

2  李四

3  王五

4  鲁班

5  黄忠

桶1里面有(实际文件名为00000):4鲁班

桶2里面有(实际文件名为00001):1 张三  5黄忠

桶3里面有(实际文件名为00002):2 李四

桶4里面有(实际文件名为00003):3 王五

(1)获得更高的查询处理效率。桶为表加上了额外的结构,hive在处理有些查询时能利用这个结构。

(2)使取样(sampling)更高效。在处理大规模数据集是,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多的方便。

创建带桶的表:

create table t_bucket(id int,name string) clustered by (id) sorted by (name) into 4 buckets row format delimited fields terminated by '\t' stored as textfile;

对于map端连接的情况,两个表以相同方式划分桶。处理左边表内某个桶的mapper直到右边表内相匹配的行在对应的桶内。因此,mapper只需要获取那个桶(这只是右边表 内存存储数据的一小部分)集可以进行连接。这已优化方法并不一定要求两个表必须桶的个数相同。两个表的桶的个数是背书关系也可以。

强制多个reduce进行输出

​​​​​​要向分桶表中填充成员,需要将hive.enforce.bucketing属性设置为true。这样。hive就知道用表定义中声明的数量来创建桶。然后使用INSERT命令即可。需要注意的是:clustered by和sorted by 不会影响数据导入,这意味着,用户必须自己负责数据如何导入,包扣数据的分桶和排序

往表中插入数据

一般对于分桶表,添加数据采用将另一个表中查询的结果INSERT到这个分桶表中

对桶中数据进行采样:

select * from t_bucket tablesample(bucket 1 out of 4 on id);

桶的个数从1开始计数,因此,前面的查询从4个桶的第一个中获取所有的用户。对于一个大规模的、均匀分布的数据集,这回返回表中四分之一的数据行。我们也可以用其他比例对若干桶进行取样。

注:tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y)
y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了64份,当y=32时,抽取(64/32=)2个bucket的数据,当y=128时,抽取(64/128=)1/2个bucket的数据。x表示从哪个bucket开始抽取。例如,table总bucket数为32,tablesample(bucket 3 out of 16),表示总共抽取(32/16=)2个bucket的数据,分别为第3个bucket和第(3+16=)19个bucket的数据。

猜你喜欢

转载自blog.csdn.net/qq_38704184/article/details/84590478