Hive进阶篇(三)创建表+表结构*(字段类型、文件格式、行格式、分区表)

一、创建表

hive建一张表结构一样的表 hive创建表结构_字段

hive建一张表结构一样的表 hive创建表结构_hive建一张表结构一样的表_02

 外部表的彻底删除参考:javascript:void(0)

二、字段类型

1、简单的

hive建一张表结构一样的表 hive创建表结构_字段_03

2、复杂的

hive建一张表结构一样的表 hive创建表结构_字段_04

三、文件格式

1、文本

log(日志文件)、csv文件(逗号分隔的)、tsv(tab分隔的)

2、JSON(一行是一个JSON)

3、Binary(二进制格式的)效率较高

     行式的(SequenceFile-用的很少了)、

     列式的(使用最广泛,Parquet(用的更多)ORC

 PARQUET举例--将TXT表转换为PARQUET表:

 (1)先建表结构

DROP TABLE IF EXISTS pq_access_logs;
CREATE TABLE pq_access_logs (
    ip STRING,
    request_time STRING,
    method STRING,
    url STRING,
    http_version STRING,
    code1 STRING,
    code2 STRING,
    dash STRING,
    user_agent STRING,
    `timestamp` int)
STORED AS PARQUET;

(2)再将TXT表中的数据加载到建好的表中

INSERT OVERWRITE TABLE pq_access_logs
SELECT 
  ip,
  from_unixtime(unix_timestamp(request_time, 'dd/MMM/yyyy:HH:mm:ss z'), 'yyyy-MM-dd HH:mm:ss z'),
  method,
  url,
  http_version,
  code1,
  code2,
  dash,
  user_agent,
  unix_timestamp(request_time, 'dd/MMM/yyyy:HH:mm:ss z')
FROM original_access_logs;

这里使用 from_unixtime 和 unix_timestamp函数将日/月/年的顺序进行调整 变成年-月-日的形式。

Parquet-二进制存储的查询效率更高

三、行格式(Row Format)

1、标准分隔符

     DELIMETED-反序列化(前面有DE表反)

     

hive建一张表结构一样的表 hive创建表结构_hive建一张表结构一样的表_05

2、需要自定义序列化类来处理

     SERDE-序列化

      

hive建一张表结构一样的表 hive创建表结构_分区表_06

四、分区表

1、按照日期进行分区

CREATE TABLE partitioned_access_log ( ip STRING,

) ...

PARTITIONED BY

hdfs:///access_logs/ ...

— 2017_01_20

— 2017_01_21

— 2017_01_22 ...

— "today" 

2、.../年/月/日 式的分区

CREATE TABLE partitioned_access_log ( ip STRING,

) ...

PARTITIONED BY (year STRING, month STRING, day STRING) ...; 

hdfs:///access_logs/ ...

— 2017

—— 01

——— 20

——— 21

——— 22 ... 

3、分区表的作用

避免全表扫描

提升查询性能 减少IO

方便数据按分区写入(覆盖)

方便管理

4、分区表的操作演示

1)创建分区表-PARTITIONED BY

DROP TABLE IF EXISTS partitioned_access_logs;
CREATE EXTERNAL TABLE partitioned_access_logs (
    ip STRING,
    request_time STRING,
    method STRING,
    url STRING,
    http_version STRING,
    code1 STRING,
    code2 STRING,
    dash STRING,
    user_agent STRING,
    `timestamp` int)
PARTITIONED BY (request_date STRING)
STORED AS PARQUET
;

STORED AS PARQUET --文件格式是列式的。

2)将日志表写入分区表,使用动态分区插入

set hive.exec.dynamic.partition.mode=nonstrict;

INSERT OVERWRITE TABLE partitioned_access_logs 
PARTITION (request_date)
SELECT ip, request_time, method, url, http_version, code1, code2, dash, user_agent, `timestamp`, to_date(request_time) as request_date
FROM pq_access_logs 
;

解释:

set hive.exec.dynamic.partition.mode=nonstrict; 是在设置环境变量,

nonstrict是将分区设置成不严格的(默认是严格的-strict),这样就能开启动态分区的插入模式了。

to_date(request_time)是将 年月日时分秒 转换成 日期的格式了。

如果是静态的话,可以看下面这个例子:

set hive.exec.dynamic.partition.mode=nonstrict;

INSERT OVERWRITE TABLE partitioned_access_logs 
PARTITION (request_date = '2020-08-10')
SELECT ip, request_time, method, url, http_version, code1, code2, dash, user_agent, `timestamp`, to_date(request_time) as request_date
FROM pq_access_logs 
where request_time >= '2020-08-10' and requset_time < '2020-08-11'
;

将2020年8月10号-2020年8月11号之间的数据全部插入到2020-08-10的分区中。

当然因为一年有365天左右,这样静态的话就得写好多遍这段demo了,所以还是采用动态的更高效。

当然,动态分区和静态分区也是可以混用的-混合分区:

set hive.exec.dynamic.partition.mode=nonstrict;

INSERT OVERWRITE TABLE partitioned_access_logs 
PARTITION (year = '2020', month = '06', day)
SELECT ip, request_time, method, url, http_version, code1, code2, dash, user_agent, `timestamp`, to_date(request_time) as request_date
FROM pq_access_logs 
;

3)查看分区表的分区情况

  • show partitions + 分区表表名

  (直接通过元数据进行查询,效率最高。有的时候分区多的话,结果的时间会是无序的了)

  • 还有一种是select distinct + 分区根据的属性名 + from

  (需要从HDFS将文件读一遍才可得到结果,较慢)

0: jdbc:hive2://localhost:10000> show partitions partitioned_access_logs;

结果:

+--------------------------+--+

|        partition         |

+--------------------------+--+

| request_date=2014-06-14  |

| request_date=2014-06-15  |

+--------------------------+--+

2 rows selected (0.277 seconds)

有两个分区创建出来了-两天的日志信息

4)看分区表的目录形式

[root@cdh alternatives]# hdfs dfs -ls /user/hive/warehouse/partitioned_access_logs/

Found 2 items

drwxrwxrwt   - hive hive          0 2021-02-17 14:55 /user/hive/warehouse/partitioned_access_logs/request_date=2014-06-14

drwxrwxrwt   - hive hive          0 2021-02-17 14:55 /user/hive/warehouse/partitioned_access_logs/request_date=2014-06-15

可以看到该分区表的各分区之间是并列的形式

Hive的分区目录名结尾是一种key(分区字段)=value(日期)的形式,不仅仅只有日期

每个分区目录下面存的就是分区内的结果文件,文件的命名会以编号的形式按顺序拍好.

5) 分区表加字段

alter tableadd columns (要增加的分区字段名 + 数据类型);

下面的写法也可以:

alter table + 分区表名(也可以是数据库.表名的形式) + add + partition  (分区字段名 = '指定的分区名中的日期')

注:分区表新加入的字段并不能真正插入数据,

     因为老的分区结构是在表结构刚建好之后就保存在元数据中的,是不会因为新字段的加入就改变的.

     如果要增加分区并且真正地可以插入数据的话,

  • 对于内部表:就需要删除分区表,然后再创建一个新的分区表. 因为删除个别分区之后里面的数据也会被删除.
  • 对于外部表:可先删除掉新加的分区字段所在的分区(删掉的仅仅是表结构),再将其重建即可显示出来了.   

6) 读取个别分区

select * from + 分区表的表名+ where + 分区字段名 = '指定的分区名中的日期'

也可以在后面加上 limit+行数 进行打印行数的限制

7) 删除个别分区字段

alter table + 分区表名(也可以是数据库.表名的形式) + drop + partition  (分区字段名 = '指定的分区名中的日期')

hive建一张表结构一样的表 hive创建表结构_hive建一张表结构一样的表_07

 五、Storage Handler

通过创建一个外部表 Create External Table to Export Data

将数据导入到不同的数据库中 像:

1.HBase

2.ElasticSearch