hive-02
1.数据类型
- Hive数据类型如下:
Hive数据类型 | Java数据类型 | 长度 | 例子 |
---|---|---|---|
TINYINT | byte | 1byte有符号整数 | 20 |
SMALINT | short | 2byte有符号整数 | 20 |
INT | int | 4byte有符号整数 | 20 |
BIGINT | long | 8byte有符号整数 | 20 |
BOOLEAN | boolean | 布尔类型,true或者false | TRUE FALSE |
FLOAT | float | 单精度浮点数 | 3.14159 |
DOUBLE | double | 双精度浮点数 | 3.14159 |
STRING | string | 字符系列。可以指定字符集。可以使用单引号或者双引号。 | ‘now is the time’ “for all good men” |
TIMESTAMP | 时间类型 | ||
BINARY | 字节数组 |
对于Hive的String类型相当于数据库的varchar类型,该类型是一个可变的字符串,不过它不能声明其中最多能存储多少个字符,理论上它可以存储2GB的字符数。
2 集合数据类型
- Hive有三种复杂数据类型ARRAY、MAP 和 STRUCT。ARRAY和MAP与Java中的Array和Map类似,而STRUCT与C语言中的Struct类似,它封装了一个命名字段集合,复杂数据类型允许任意层次的嵌套。
数据类型 | 描述 | 语法示例 |
---|---|---|
STRUCT | 和c语言中的struct类似,都可以通过“点”符号访问元素内容。例如,如果某个列的数据类型是STRUCT{first STRING, last STRING},那么第1个元素可以通过字段.first来引用。 | struct() |
MAP | MAP是一组键-值对元组集合,使用数组表示法可以访问数据。例如,如果某个列的数据类型是MAP,其中键->值对是’first’->’John’和’last’->’Doe’,那么可以通过字段名[‘last’]获取最后一个元素 | map() |
ARRAY | 数组是一组具有相同类型和名称的变量的集合。这些变量称为数组的元素,每个数组元素都有一个编号,编号从零开始。例如,数组值为[‘John’, ‘Doe’],那么第2个元素可以通过数组名[1]进行引用。 | Array() |
3.示例演示:
- 示例:假设某表有如下一行,我们用JSON格式来表示其数据结构
{
"name": "songsong",
"friends": ["bingbing" , "lili"] , //列表Array,
"children": { //键值Map,
"xiao song": 18 ,
"xiaoxiao song": 19
}
"address": { //结构Struct,
"street": "hui long guan" ,
"city": "beijing"
}
}
- 而在本地txt存储文件夹格式为,这里放在本地
/data/teacher.txt
songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,hui long guan_beijing
yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,chao yang_beijing
- 那我们通过如下方式创建表:
create table if not exists teacher(
name string,
friends array<string>,
children map<string, int>,
address struct<street:string, city:string>
)
row format delimited fields terminated by ","--列分割符
collection items ternubated by "_"--集合的分隔符
map keys terminated by ":"--map 中key和value的分隔符
lines terminated by "
";--换行分隔符
- 加载数据
load data local inpath "/data/teacher.txt" into table teacher;
- 查询数据验证
0: jdbc:hive2://linux01:10000> select * from teacher;
+---------------+----------------------+--------------------------------------+----------------------------------------------+
| teacher.name | teacher.friends | teacher.children | teacher.address |
+---------------+----------------------+--------------------------------------+----------------------------------------------+
| songsong | ["bingbing","lili"] | {"xiao song":18,"xiaoxiao song":19} | {"street":"hui long guan","city":"beijing"} |
| yangyang | ["caicai","susu"] | {"xiao yang":18,"xiaoxiao yang":19} | {"street":"chao yang","city":"beijing"} |
+---------------+----------------------+--------------------------------------+----------------------------------------------+
- Array中数据查询:
# 通过索引进行查询
select name, friends[0] from teacher;
- Map中数据查询
# 查询Map中所有key
select name,map_keys(children) from teacher;
# 指定key查询value
select name,children["xiao song"] from teacher;
# 查询指定key,value
select name,map_keys(children)[0],map_values(children)[0] from teacher;
- Struct中数据查询
# "点"语法查询struct中属性
select name,address.street from teacher;
4.内部表与外部表互换
- 通过
desc formatted 表名
命令查看表的类型:
desc formatted teacher;
...
| Table Type: | MANAGED_TABLE
- 上面通过命令查询到teacher表为内部部表,如何更改为外部表呢??
# 内部表转外部表
alter table teacher set tblproperties('EXTERNAL'='TRUE');
# 外部表转内部表
alter table teacher set tblproperties('EXTERNAL'='FALSE');
5.表结构的修改
- 更改表名
alter table 老表名 rename to 新表名;
- 添加
alter table 表名 add columns(字段名 数据类型)
- 更新列
alter table 表名 change column 老字段名 新字段名 新数据类型;
- 替换列
alter table 表名 replace columns(字段名 数据类型, 字段名
数据类型, 字段名 数据类型);
6.分区表
- 分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。
6.1静态分区(分文件夹)
- 准备文件
# 1.txt
1 2020-05-05 30
3 2020-05-11 40
5 2020-05-22 66
# 2.txt
7 2020-05-27 31
9 2020-05-39 44
# a.txt
2 2020-06-01 11
4 2020-06-02 22
6 2020-06-03 33
8 2020-06-04 44
- 创建基础表
create table test1(
uid int,
dy string,
money int
)
row format delimited fields terminated by " ";
- 将本地数据加载hive
load data local inpath "/data/1.txt" into table test1;
load data local inpath "/data/2.txt" into table test1;
load data local inpath "/data/a.txt" into table test1;
- 此时数据如下
+------------+-------------+--------------+
| test1.uid | test1.dy | test1.money |
+------------+-------------+--------------+
| 1 | 2020-05-05 | 30 |
| 3 | 2020-05-11 | 40 |
| 5 | 2020-05-22 | 66 |
| 7 | 2020-05-27 | 31 |
| 9 | 2020-05-39 | 44 |
| 2 | 2020-06-01 | 11 |
| 4 | 2020-06-02 | 22 |
| 6 | 2020-06-03 | 33 |
| 8 | 2020-06-04 | 44 |
+------------+-------------+--------------+
- 当我们执行查询
2020-06
的数据时候,它会检索hdfs刚才导入的三个文件数据,然后筛选出匹配的,这样会很慢。
select * from test1 where dy like "2020-06%"
我们可以创建分区表,减少检索文件数,从而提高查询效率。
- 创建分区表:
create table test2(
uid int,
dy string,
money int
)
partitioned by (mn string) -- 添加分区字段
row format delimited fields terminated by " ";
# partitioned 指定分区字段
- 加载数据,通过partition设置mn,进行分区。
load data local inpath "/data/1.txt" into table test2 partition(mn="202005");
load data local inpath "/data/2.txt" into table test2 partition(mn="202005");
load data local inpath "/data/a.txt" into table test2 partition(mn="202006");
- 查询语句,这样只查寻2020-06的文件
0: jdbc:hive2://linux01:10000> select * from test2 where mn="202006";
- 上述分区是静态分区,我们指定某些数据加载到文件夹中,也就是将数据进行分类,减少查询范围,提高查询效率。
6.2二级分区创建
- 当我们业务不但想按年查也想按照月分查询,比如2015,2016....年,又有1,2,3,4...月,这样我们需要创建二级分区表
create table test3(
uid int,
dy string,
money int
)
partitioned by (y string, m string) -- y代表年分区,m代表月分区
row format delimited fields terminated by " ";
- 加载数据也需要有所改变
load data local inpath "/data/1.txt" into table test3 partition(y="2020",m="05");
load data local inpath "/data/2.txt" into table test3 partition(y="2020",m="05");
load data local inpath "/data/a.txt" into table test3 partition(y="2020",m="06");
- 查询
select * from test3 where y="2020" and m="05";
- 多级分区也是一样。。。
6.3动态分区
-
按照表中某个字段的值进行分区
-
示例演示:
1 创建普通的表 create table demo( id int , birthday string , cost int ) row format delimited fields terminated by ' ' ; 2加载数据 load data local inpath '/data/demo' into table demo ; 3.数据为 1 2010-11-12 120 2 2010-11-12 121 3 2010-11-12 122 4 2010-11-12 124 5 2010-11-13 122 6 2010-11-13 120 7 2010-11-14 123 8 2010-11-13 1202 9 2010-11-12 1202 10 2010-11-12 1201 4.创建分区表 create table demo2( id int , cost int ) partitioned by(birthday string) -- 按照birthday分区,按照哪个字段分区,哪个字段不应该在demo2表中 row format delimited fields terminated by ' ' ; 5 设置参数 set hive.exec.dynamic.partition=true //使用动态分区 set hive.exec.dynamic.partition.mode=nonstrick;//无限制模式,如果模式是strict,则必须有一个静态分区且放在最前面 6.加载数据 insert into table demo2 partition(birthday) select id, cost,birthday from demo; --注意顺序
-
此时执行查询:
select * from demo2 where y="2020" and m="06";
-
其他设置参数
set hive.exec.max.dynamic.partitions.pernode=10000;//每个节点生成动态分区的最大个数 set hive.exec.max.dynamic.partitions=100000;//生成动态分区的最大个数 set hive.exec.max.created.files=150000;//一个任务最多可以创建的文件数目 set dfs.datanode.max.xcievers=8192;//限定一次最多打开的文件数 set hive.merge.mapfiles=true; //map端的结果进行合并 set mapred.reduce.tasks =20000; //设置reduce task个数