当前位置:   article > 正文

hadoop组件---数据仓库(二)---hive的数据模型和数据类型

hadoop组件---数据仓库(二)---hive的数据模型和数据类型

我们在上一章中已经大概了解了Hive有四种数据模型,本章就来详细了解它们的使用。
Hadoop组件—数据仓库(一)—Hive简介

数据模型

Hive 没有专门的数据存储格式,也没有为数据建立索引,用户可以非常自由的组织 Hive 中的表,只需要在创建表的时候告诉 Hive 数据中的列分隔符和行分隔符,Hive 就可以解析数据。Hive 中所有的数据都存储在 HDFS 中,Hive 中包含以下数据模型:表(Table),外部表(External Table),分区(Partition),桶(Bucket)。

注:如果不指定分割符的话,Hive默认的分隔符是\001

如图所示,表=》分区=》桶,它们的对数据的划分粒度越来越小。

Hive 中的 Table 和数据库中的 Table 在概念上是类似的,每一个 Table 在 Hive 中都有一个相应的目录存储数据。例如,一个表 pvs,它在 HDFS 中的路径为:/wh/pvs,其中,wh 是在 Hive-site.xml 中由 ${Hive.metastore.warehouse.dir} 指定的数据仓库的目录,所有的 Table 数据(不包括 External Table)都保存在这个目录中。

创建表

Create table test_tb1 (flied string);
Load data local inpath ‘home/Hadoop/test.txt’ into table test_tb1;
  • 1
  • 2

外部表

Table的创建过程和数据加载过程(这两个过程可以在同一个语句中完成),在加载数据的过程中,实际数据会被移动到数据仓库目录中;之后对数据对访问将会直接在数据仓库目录中完成。删除表时,表中的数据和元数据将会被同时删除。

External Table 指向已经在 HDFS 中存在的数据,可以创建 Partition。它和 Table 在元数据的组织上是相同的,而实际数据的存储则有较大的差异。External Table 只有一个过程,加载数据和创建表同时完成(CREATE EXTERNAL TABLE ……LOCATION),实际数据是存储在 LOCATION 后面指定的 HDFS 路径中,并不会移动到数据仓库目录中。当删除一个 External Table 时,仅删除元数据,表中的数据不会真正被删

创建外部表

Create external table external_tbl (flied string)
Location  ‘/home/Hadoop/external_table’;
Load data local inpath ‘home/Hadoop/test.txt’ into table external_tbl;
  • 1
  • 2
  • 3

大家看到了创建外部表时候table之前要加关键字external,同时还要用location命令指定文件存储的路径,如果不使用locaction数据文件也会放置到Hive的数据仓库里。

这两种表在使用的区别主drop命令上,drop是Hive删除表的命令,托管表执行drop命令的时候,会删除元数据和存储的数据,而外部表执行drop命令时候只删除元数据库里的数据,而不会删除存储的数据。另外我还要谈谈表的load命令,Hive加载数据时候不会对元数据进行任何检查,只是简单的移动文件的位置,如果源文件格式不正确,也只有在做查询操作时候才能发现,那个时候错误格式的字段会以NULL来显示。

分区

Partition 对应于数据库中的 Partition 列的密集索引,但是 Hive 中 Partition 的组织方式和数据库中的很不相同。在 Hive 中,表中的一个 Partition 对应于表下的一个目录,所有的 Partition 的数据都存储在对应的目录中。例如:pvs 表中包含 ds 和 city 两个 Partition,则对应于 ds = 20090801, ctry = US 的 HDFS 子目录为:/wh/pvs/ds=20090801/ctry=US;对应于 ds = 20090801, ctry = CA 的 HDFS 子目录为;/wh/pvs/ds=20090801/ctry=CA
注意:表中可以不包括Partition字段

创建分区

Create table logs(ts bigint,line string)
Partitioned by (dt string,country string);
  • 1
  • 2

加载数据:

Local data local inpath ‘/home/Hadoop/par/file01.txt’ into table logs partition (dt=2018-01-09’,country=cn’);
  • 1

在Hive数据仓库里实际存储的路径如下所示:

/user/Hive/warehouse/logs/dt=2018-01-09/country=cn/file1.txt
/user/Hive/warehouse/logs/dt=2018-01-09/country=cn/file2.txt
/user/Hive/warehouse/logs/dt=2018-01-09/country=us/file3.txt
/user/Hive/warehouse/logs/dt=2018-01-09/country=us/file4.txt
  • 1
  • 2
  • 3
  • 4

我们看到在表logs的目录下有了两层子目录dt=2018-01-09和country=cn

查询操作:

Select ts,dt,line  from logs where country=’cn’,
  • 1

这个时候我们的查询操作只会扫描file1.txt和file2.txt文件。

Buckets 对指定列计算 hash,根据 hash 值切分数据,目的是为了并行,每一个 Bucket 对应一个文件。例如将 user 列分散至 32 个 bucket,首先对 user 列的值计算 hash,对应 hash 值为 0 的 HDFS 目录为:/wh/pvs/ds=20180109/ctry=US/part-00000;hash 值为 20 的 HDFS 目录为:/wh/pvs/ds=20180109/ctry=US/part-00020

上面的table和partition都是目录级别的拆分数据,bucket则是对数据源数据文件本身来拆分数据。使用桶的表会将源数据文件按一定规律拆分成多个文件,要使用bucket,我们首先要打开Hive对桶的控制,命令如下:

set Hive.enforce.bucketing = true
  • 1

示例:
建临时表student_tmp,并导入数据:

Hive> desc student_tmp;
OK
id      int
age     int
name    string
stat_date       string
Time taken: 0.102 seconds
Hive> select * from student_tmp;
OK
1       27      zzq     20180109
2       19      ly      20180109
3       26      lmz     20180109
4       27      gsq     20180109
5       27      ysl     20180109
6       26      yys     20180109
7       27      xg      20180109
Time taken: 0.116 seconds
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

建student表:

Hive>create table student(id INT, age INT, name STRING)
       >partitioned by(stat_date STRING) 
       >clustered by(id) sorted by(age) into 2 bucket
       >row format delimited fields terminated by ',';
  • 1
  • 2
  • 3
  • 4

设置环境变量:

       >set Hive.enforce.bucketing = true;
  • 1

插入数据:

   >from student_tmp 
   >insert overwrite table student partition(stat_date="20180203") 
   >select id,age,name where stat_date="20180109" sort by age;
  • 1
  • 2
  • 3

查看文件目录:

$ Hadoop fs -ls /user/Hive/warehouse/studentstat_date=20180203/
Found 2 items
-rw-r--r--   1 work joe         31 2018-01-09 19:07 /user/Hive/warehouse/student/stat_date=20180203/000000_0
-rw-r--r--   1 work joe         39 2018-01-09 19:07 /user/Hive/warehouse/student/stat_date=20180203/000001_0
  • 1
  • 2
  • 3
  • 4

物理上,每个桶就是表(或分区)目录里的一个文件,桶文件是按指定字段值进行hash,然后除以桶的个数例如上面例子2,最后去结果余数,因为整数的hash值就是整数本身,上面例子里,字段hash后的值还是字段本身,所以2的余数只有两个0和1,所以我们看到产生文件的后缀是*0_0和*1_0,文件里存储对应计算出来的元数据。

Hive的桶,我个人认为没有特别的场景或者是特别的查询,我们可以没有必要使用,也就是不用开启Hive的桶的配置。因为桶运用的场景有限,一个是做map连接的运算,一个就是取样操作:

查看sampling数据:

Hive> select * from student tablesample(bucket 1 out of 2 on id);                                                                               
Total MapReduce jobs = 1
Launching Job 1 out of 1
.......
OK
2       19      ly      20180109
6       26      yys     20180109
4       27      gsq     20180109
Time taken: 18.253 seconds
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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的数据。

数据类型

Hive支持两种数据类型,一类叫原子数据类型,一类叫复杂数据类型。

原子类型

原子数据类型包括数值型、布尔型和字符串类型,具体如下表所示:

由上表我们看到Hive不支持日期类型,在Hive里日期都是用字符串来表示的,而常用的日期格式转化操作则是通过自定义函数进行操作。

Hive是用java开发的,Hive里的基本数据类型和java的基本数据类型也是一一对应的,除了string类型。有符号的整数类型:TINYINT、SMALLINT、INT和BIGINT分别等价于java的byte、short、int和long原子类型,它们分别为1字节、2字节、4字节和8字节有符号整数。Hive的浮点数据类型FLOAT和DOUBLE,对应于java的基本类型float和double类型。而Hive的BOOLEAN类型相当于java的基本数据类型boolean。

对于Hive的String类型相当于数据库的varchar类型,该类型是一个可变的字符串,不过它不能声明其中最多能存储多少个字符,理论上它可以存储2GB的字符数。

Hive支持基本类型的转换,低字节的基本类型可以转化为高字节的类型,例如TINYINT、SMALLINT、INT可以转化为FLOAT,而所有的整数类型、FLOAT以及STRING类型可以转化为DOUBLE类型,这些转化可以从java语言的类型转化考虑,因为Hive就是用java编写的。当然也支持高字节类型转化为低字节类型,这就需要使用Hive的自定义函数CAST了。

复杂类型

复杂数据类型包括数组(ARRAY)、映射(MAP)和结构体(STRUCT),具体如下表所示:

下面我们看看Hive使用复杂数据类型的实例,建表:

Create table complex(col1 ARRAY<INT>,
Col2 MAP<STRING,INT>,
Col3 STRUCT<a:STRING,b :INT,c:DOUBLE>);
  • 1
  • 2
  • 3

查询语句:

Select col1[0],col2[‘b’],col3.c from complex;
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/597313
推荐阅读
相关标签
  

闽ICP备14008679号