热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

外部表

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;

大家看到了创建外部表时候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);

加载数据:

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

在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

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

查询操作:

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

这个时候我们的查询操作只会扫描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

示例:
建临时表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

建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 ',';

设置环境变量:

       >set Hive.enforce.bucketing = true;

插入数据:

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

查看文件目录:

$ 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

物理上,每个桶就是表(或分区)目录里的一个文件,桶文件是按指定字段值进行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

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 MAPINT
>,
Col3 STRUCTINT,c:DOUBLE>);

查询语句:

Select col1[0],col2[‘b’],col3.c from complex;

推荐阅读
  • 处理Android EditText中数字输入与parseInt方法
    本文探讨了如何在Android应用中从EditText组件安全地获取并解析用户输入的数字,特别是用于设置端口号的情况。通过示例代码和异常处理策略,展示了有效的方法来避免因非法输入导致的应用崩溃。 ... [详细]
  • 本文详细介绍了Oracle 11g中的创建表空间的方法,以及如何设置客户端和服务端的基本配置,包括用户管理、环境变量配置等。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • 本文介绍了如何通过C#语言调用动态链接库(DLL)中的函数来实现IC卡的基本操作,包括初始化设备、设置密码模式、获取设备状态等,并详细展示了将TextBox中的数据写入IC卡的具体实现方法。 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • 本文详细探讨了在Web开发中常见的UTF-8编码问题及其解决方案,包括HTML页面、PHP脚本、MySQL数据库以及JavaScript和Flash应用中的乱码问题。 ... [详细]
  • 本文探讨了如何在PHP与MySQL环境中实现高效的分页查询,包括基本的分页实现、性能优化技巧以及高级的分页策略。 ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 本文探讨了如何将个人经历,特别是非传统的职业路径,转化为职业生涯中的优势。通过作者的亲身经历,展示了舞蹈生涯对商业思维的影响。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • spring boot使用jetty无法启动 ... [详细]
  • Android与JUnit集成测试实践
    本文探讨了如何在Android项目中集成JUnit进行单元测试,并详细介绍了修改AndroidManifest.xml文件以支持测试的方法。 ... [详细]
  • 深入理解:AJAX学习指南
    本文详细探讨了AJAX的基本概念、工作原理及其在现代Web开发中的应用,旨在为初学者提供全面的学习资料。 ... [详细]
  • flea,frame,db,使用,之 ... [详细]
author-avatar
清澈小溪-
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有