1. 什么是Hive

Hive是facebook开发的,是一个基于Hadoop的一个数据仓库工具,可以将结构化的数据映射为一张数据库表,并且提供HQL,也就是Hive SQL查询功能,底层数据实际上是存储在HDFS上面的。

那么Hive的本质其实是将SQL语句转化为MapReduce任务运行的,可以让不熟悉MR的用户可以简单的通过Hive SQL来访问HDFS上结构化的数据,并且Hive适用于离线的批量数据计算。

Hive的特点:

  1. 可拓展性强,可以自由的拓展集群的规模,一般不需要重启服务横向拓展。
  2. 延展性强,Hive支持自定义函数
  3. 良好的容错性,可以保证即使节点出现问题,SQL语句也能完成执行
  4. Hive查询延时很严重,因为MapReduce job启动过程需要消耗很长的时间,所以一般不用在交互查询系统里面
  5. Hive不支持事务,主要是做OLAP联机分析处理,而不是OLTP联机事务处理

2. Hive的架构:

Hive理解 hive详解_数据

上面的Thrift server是facebook开发的一个软件框架????,用来进行可拓展且跨语言的服务开发,Hive集成了这个就是为了让不同的变成语言来调用Hive的接口


3. Hive表:

※ 内表和外表的区别:

删除内部表,删除表的元数据和数据

删除外部表,删除元数据,但是不会删除具体数据

如果我们所有的处理都是在Hive中进行的,那么我们倾向于选择内部表,但是如果Hive和其他的工具需要对同一个数据集进行处理,那么外部表更合适。

所以Hive其实只是对存储在HDFS上的数据提供了一种新的抽象,而不是管理存储在HDFS上的数据。

※ Hive的文件存储格式:

Hive 主要有五种文件存储格式:

  1. TEXTFILE:
    这是默认格式,导入数据的时候会直接把数据文件拷贝到HDFS上面不进行处理,存储方式为行存储,磁盘开销大,数据解析开销大,而且hive不会对数据进行切分,所以无法对数据进行并行操作。
    Tips: 后面的格式不能直接从本地文件导入数据,所以如果使用load data来向hive表里面插入数据,需要先导入到textfile格式的表中,然后再从这个表导入到其他的格式表中。
    其实就是其他的格式需要走MR,因为其他类型都涉及了文件的压缩,所以需要借助MR的压缩方式。
  2. SEQUENCEFILE:
    二进制文件,以k,v形式序列化到文件中,存储方式是行存储,可以分割压缩,优势是文件和Hadoop API中的mapfile是兼容的
  3. RCFILE:
    数据按照行分块,每一块都是列存储,压缩快
    读取需要的列只需要读取每个row group中的头部定义,但是读取全量的数据对比上面的没有明显的优势
  4. ORCFILE (0.11版本之后):
    跟上面的RCFILE差不多,是上面格式的改良版,orc表解决小文件数的方法是可以用hive的concatenate将小文件合并。
Alter table XXX.XXX_orc partition (create_time = '2021-04-12') concatenate;
  1. PARQUET:
    类似于ORC,Hadoop生态系统中的大部分工程都支持这种类型的文件。


其实三种主流的就是TEXTFILE,ORC,PARQUET

压缩比:ORC > Parquet > textFile(textfile没有进行压缩)

※ Load data 时Hive的分隔符:

CREATE EXTERNAL TABLE `dw_ads.ads_temp_pro_user`(
      `user_uuid` string COMMENT '用户ID', 
      `user_name` string COMMENT '姓名', 
      `mobile` string COMMENT '手机号')
PARTITIONED BY (`type` string)
row format delimited 
    FIELDS TERMINATED BY '\t'
    COLLECTION ITEMS TERMINATED BY '\002'
    MAP KEYS TERMINATED BY '\003'
    LINES TERMINATED BY '\n';

ROW FORMAT DELIMITED 这个关键字是用来设置创建表在加载数据的时候,支持的列分隔符,那么Hive表默认的分隔符如下:

分隔符

描述

\n

行分隔符

^A

字段分隔符 \001

^B

array、struct的元素间的分隔符,map的键值对与键值对间分隔符 \002

^C

map中键与值之间的 分隔符\003

那么如果我们要修改一个已有表的分隔符:

alter table dw_ads.ads_temp_pro_user set SERDEPROPERTIES('field.delim'='\t');

4. Hive小文件处理:

Hive数据存储的底层是HDFS,HDFS一般对小文件数会有限制,当数据量大了,那我们治理小文件数就是一件很痛苦的事情。

针对ORC表:

针对orc表比较简单,因为可以直接使用concatenate命令进行数据的合并压缩来减少小文件

针对某一天的分区concatenate:

Alter table XXX.XXX_orc partition (create_time = '2021-04-12') concatenate;

很多情况我们期望有周期性的任务来每天自动合并前一天的分区,hive虽然有current_date()方法,但是配合concatenate的时候无法使用,那么我们可以用shell命令来创建周期任务:

hive --hivevar today=$(date -d "-1 day" +"%Y-%m-%d") -e 'Alter table xxx.xxx_orc partition (create_time = date '\''${hivevar:today}'\'') concatenate'

针对TextFile表:

针对TextFile就很麻烦了,因为这种表格式是不支持concatenate合并的,但是我发现有一种方法能减少大量的文件数,那就是将一个月(时间范围可以根据需求自定)的分区数据重新插入一个新的分区,原理我猜是重新插入走了MapReduce方式,所以新分区的文件数不会很多。

首先将时间范围内的数据select并插入一个新的没有数据的分区:

INSERT INTO TABLE xxx_database.xxx_table partition (create_time = "2021-02-01") 
SELECT col1, col2, col3, col4
FROM xxx_database.xxx_table where create_time >= '2021-03-01' and create_time <= '2021-03-31';

然后删除原来的分区:

Alter table xxx_database.xxx_table drop partition (create_time <= '2021-03-31', create_time >= '2021-03-01');