Fork me on GitHub

hive-02

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 "\n";--换行分隔符
  • 加载数据
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 "\t";

  • 将本地数据加载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 "\t";
# 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 "\t";
  • 加载数据也需要有所改变
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 '\t' ;
    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 '\t' ;
    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个数
    
posted @ 2021-02-01 15:21  是阿凯啊  阅读(72)  评论(0编辑  收藏  举报