大数据开发工程师-第八周 第4章 Hive核心实战2


第八周 第4章 Hive核心实战

Hive中的数据类型

1
2
3
4
5
6
hive作为一个类似数据库的框架,也有自己的数据类型,便于存储、统计、分析。
Hive中主要包含两大数据类型
一类是基本数据类型
一类是复合数据类型
基本数据类型:常用的有INT,STRING,BOOLEAN,DOUBLE等
复合数据类型:常用的有ARRAY,MAP,STRUCT等

基本数据类型

1
2
3
4
看这个表,一般数字类型我们可以试验int,小数可以使用double,日期可以使用date类型、还有就是
boolean类型,这些算是比较常见的了,前面我们在建表的时候基本都用过了。

这些基本数据类型倒没有什么特殊之处

image-20230319234341573

1
2
3
4
5
6
7
8
数据类型 开始支持版本 数据类型 开始支持版本
TINYINT ~ TIMESTAMP 0.8.0
SMALLINT ~ DATE 0.12.0
INT/INTEGER ~ STRING ~
BIGINT ~ VARCHAR 0.12.0
FLOAT ~ CHAR 0.13.0
DOUBLE ~ BOOLEAN ~
DECIMAL 0.11.0

复合数据类型

1
下面主要看一下复合数据类型,在这里我们主要分析这三个, array,map和struct

image-20230319234903529

Array

1
2
3
4
5
6
7
8
9
先来看Array,这个表示是一个数组结构
在这里举一个例子:学生有多个爱好,有两个学生,zhangsan、lisi,
zhangsan的爱好是swing、sing、coding
lisi的爱好是music、football
每个学生的爱好都是不固定的,有多有少,如果根据学生的每一个爱好都在表里面增加一列,这样就不合适了,后期可能要经常增加列存储不同的爱好

如果我们如果把每个学生的爱好都拼接为一个字符串保存到一个字段中,这样针对存储层面来说是没有问题的,但是后期需要根据爱好的增加而修改字段,这样操作起来很不方便,如果想获取每个学生的1个爱好,这样是没办法直接获取的,因为这些爱好是以字符串的形式保存在一个字段中的

为了方便存储和使用,我们针对学生的爱好这种数据个数不固定的场景,可以使用数组的形式来存储测试数据是这样的
1
2
3
[root@bigdata04 hivedata]# more stu.data
1 zhangsan swing,sing,coding
2 lisi music,football
1
2
3
4
5
6
7
8
9
10
来建一张表,指定了一个array数组类型的字段叫favors,数组中存储字符串,数组中的元素怎么分割呢?通过 collection items terminated by ',' 指定的

create table stu(
id int,
name string,
favors array<string>
)row format delimited
fields terminated by '\t'
collection items terminated by ','
lines terminated by '\n';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
hive (default)> load data local inpath '/data/soft/hivedata/stu.data' into table stu
Loading data to table default.stu
OK
Time taken: 1.478 seconds


查询数组中的某一个元素,使用 arrayName[index]
hive (default)> select * from stu;
OK
stu.id stu.name stu.favors
1 zhangsan ["swing","sing","coding"]
2 lisi ["music","football"]
Time taken: 1.547 seconds, Fetched: 2 row(s)


hive (default)> select id,name,favors[1] from stu;
OK
id name _c2

1 zhangsan sing
2 lisi football
Time taken: 0.631 seconds, Fetched: 2 row(s)
1
2
角标是从0开始的,如果获取到了不存在的角标则返回null
这就是Array类型的使用了

Map

1
2
3
4
5
6
下面来说一下另外一种常见的集合——map,我们知道map集合里面存储的是键值对,每一个键值对属于Map集合的一个item,
这里给大家举个例子,有两个学生zhangsan、lisi,每个学生有语文、数学、英语,成绩如下:

[root@bigdata04 hivedata]# more stu2.data
1 zhangsan chinese:80,math:90,english:100
2 lisi chinese:89,english:70,math:88
1
2
3
4
5
6
7
8
9
10
11
12
13
14
针对学生的成绩信息最好也是存储到一个字段中,方便管理和使用,发现学生的成绩都是key-value类型的,所以非常适合使用map类型
建表语句如下:指定scores字段类型为map格式
通过 collection items terminated by ',' 指定了map中元素之间的分隔符
通过 map keys terminated by ':' 指定了key和value之间的分隔符

create table stu2(
id int,
name string,
scores map<string,int>
)row format delimited
fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':'
lines terminated by '\n';
1
2
3
4
5
6
7
8
9
10
11
hive (default)> load data local inpath '/data/soft/hivedata/stu2.data' into table stu2
Loading data to table default.stu2
OK
Time taken: 0.521 seconds

查看表中的数据
hive (default)> select * from stu2;
OK
stu2.id stu2.name stu2.scores
1 zhangsan {"chinese":80,"math":90,"english":100}
2 lisi {"chinese":89,"english":70,"math":88}
1
2
3
4
5
6
7
查询所有学生的语文和数学成绩
hive (default)> select id,name,scores['chinese'] as ch_score ,scores['math'] as math_score from stu2;

id name ch_score math_score
1 zhangsan 80 90
2 lisi 89 88
Time taken: 0.232 seconds, Fetched: 2 row(s)
1
在这注意一下,我们取数据是根据元素中的key获取的,和map结构中元素的位置没有关系

Struct

1
2
3
4
5
再来介绍最后一种复合类型struct,有点像java中的对象,举个例子说明一下,某学校有2个实习生,zhangsan、lisi,每个实习生都有地址信息,一个是户籍地所在的城市,一个是公司所在的城市,我们来组织一下数据

[root@bigdata04 hivedata]# more stu3.data
1 zhangsan bj,sh
2 lisi gz,sz
1
2
3
4
5
6
7
8
9
10
11
12
13
针对这里面的地址信息,不能懒省事使用字符串,否则后期想要获取他们对应的户籍地城市或者公司所在的城市信息时就比较麻烦了

所以在这我们可以考虑使用Struct类型
建表语句如下:

create table stu3(
id int,
name string,
address struct<home_addr:string,office_addr:string>
)row format delimited
fields terminated by '\t'
collection items terminated by ','
lines terminated by '\n';
1
2
3
4
hive (default)> load data local inpath '/data/soft/hivedata/stu3.data' into t
Loading data to table default.stu3
OK
Time taken: 0.447 seconds
1
2
3
4
5
6
7
8
9
10
11
12
13
14
hive (default)> select * from stu3;
OK
stu3.id stu3.name stu3.address
1 zhangsan {"home_addr":"bj","office_addr":"sh"}
2 lisi {"home_addr":"gz","office_addr":"sz"}
Time taken: 0.189 seconds, Fetched: 2 row(s)
hive (default)> select id,name,address.home_addr from stu3;
OK
id name home_addr
1 zhangsan bj
2 lisi gz
Time taken: 0.201 seconds, Fetched: 2 row(s)

在这里大家会发现其实这个需求,我们使用Array也是可以搞定的吧,只不过是在查询的时候只能通过角标访问,不太方便而已。

Struct和Map的区别

1
2
3
4
5
6
7
8
9
10
11
如果从建表语句上来分析,其实这个Struct和Map还是有一些相似之处的

来总结一下:
map中可以随意增加k-v对的个数
struct中的k-v个数是固定的
map在建表语句中需要指定k-v的类型
struct在建表语句中需要指定好所有的属性名称和类型
map中通过[]取值
struct中通过.取值,类似java中的对象属性引用
map的源数据中需要带有k-v
struct的源数据中只需要有v即可
1
2
3
总体而言还是map比较灵活,但是会额外占用磁盘空间,因为他比struct多存储了数据的key

struct只需要存储value,比较节省空间,但是灵活性有限,后期无法动态增加k-v

案例:复合数据类型的使用

1
2
3
4
5
6
在这里我们把前面学到的这三种复合数据类型结合到一块来使用一下。
有一份数据是这样的

[root@bigdata04 hivedata]# more student.data
1 zhangsan english,sing,swing chinese:80,math:90,english:10 bj,sh
2 lisi games,coding chinese:89,english:70,math:88 gz,sz
1
2
根据这份数据建表,根据咱们前面的学习,这里面这几个字段分别是int类型、string类型,array类型,map类型,struct类型
其实也不一定非要使用这些复合类型,主要是需要根据具体业务分析,使用复合数据类型可以更方便的操作数据
1
2
3
4
5
6
7
8
9
10
11
create table student (
id int comment 'id',
name string comment 'name',
favors array<string> ,
scores map<string, int>,
address struct<home_addr:string,office_addr:string>
) row format delimited
fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':'
lines terminated by '\n';
1
2
3
4
5
6
7
8
hive (default)> load data local inpath '/data/soft/hivedata/student.data' into table student;

hive (default)> select * from student;
OK
student.id student.name student.favors student.scores student.addre
1 zhangsan ["english","sing","swing"] {"chinese":80,"math":
2 lisi ["games","coding"] {"chinese":89,"english":70,"math":88}
Time taken: 0.168 seconds, Fetched: 2 row(s)

思考题

1
2
3
4
5
6
7
问:在mysql中有一张表student(id,name),还有一张表address(stu_id,home,school),还有联系方式表contact(stu_id,mine,parents,others)。如果把这三张表迁移到hive中,如何迁移?
答:
可以一一对应迁移,优点是迁移成本非常低,包括DDL和业务逻辑,几乎不需要修改,可以直接使用。缺点是产生大量的表连接,造成查询慢。
可以一对多,mysql中的多张关联表可以创建为hive中的一张表。优点是减少表连接操作。缺点是迁移成本高,需要修改原有的业务逻辑。
实际上,在我们日常的开发过程中遇到这样的问题,要想比较完美、顺利的解决,一般都分为两个阶段,第一个阶段,现在快捷迁移,就是上面说的一一对应,让我们的系统能跑起来,在此基础之上呢,再做一张大表,尽量包含以上所有字段,例如:
stu(id, name, address struct<home,school>, contact struct<…>);
等第二个阶段完工之后了,就可以跑在新的系统里面了。

本文标题:大数据开发工程师-第八周 第4章 Hive核心实战2

文章作者:TTYONG

发布时间:2022年02月20日 - 12:02

最后更新:2023年06月16日 - 16:06

原始链接:http://tianyong.fun/%E5%A4%A7%E6%95%B0%E6%8D%AE%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88-%E7%AC%AC%E5%85%AB%E5%91%A8-%E7%AC%AC4%E7%AB%A0-Hive%E6%A0%B8%E5%BF%83%E5%AE%9E%E6%88%98%202-%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B.html

许可协议: 转载请保留原文链接及作者。

多少都是爱
0%