Hive 表有多种存储格式,TextFile、ORC、RCFile等等。

TextFile 的存储格式是未经压缩的纯文本格式,按指定分隔符对字段进行划分。当数据本身包含了分隔符,就会导致数据错位问题,所以使用TextFile存储数据有较大的安全隐患

如果表本身的存储格式已经是TextFile,想要转换成其他格式该如何操作?

本教程适合于Hive分区表,如果Hive表不是分区表,直接修改存储格式会导致数据读取失败!

一、查看表格式

通过建表语句,查看表本身的存储格式

命令如下:

SHOW CREATE TABLE <表名>

执行命令后会得到以下结果:

-- 返回结果有裁剪
CREATE EXTERNAL TABLE `xxx`(
  `name` bigint COMMENT '名字')
PARTITIONED BY ( 
  `xxx` xxx)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'

INPUTFORMAT、OUTPUTFORMAT 决定了表数据的读写方式,也直接决定了表的存储格式

存储格式参照表

Hive表的存储格式可以通过下表判断

OUTPUTFORMAT

存储格式

org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat

TextFile

org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat

TextFile

org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat

Orc

org.apache.hadoop.hive.ql.io.RCFileOutputFormat

RCFile

org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat

Parquet

org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat

Sequence

二、修改表存储格式

接下来的教程是修改Hive分区表的存储格式

先介绍Hive Meta中存储格式的一些概念

表存储格式 & 分区存储格式

Hive Meta 中,TBLS 是表的元数据,其中记录了表的存储格式,PARTITIONS 是分区的元数据,也记录了分区的存储格式

表存储格式分区存储格式 究竟是什么关系?存储格式又是由哪一个决定的呢?

表存储格式 表明了Hive表的存储格式,新增的分区将跟随表的存储格式,即

新增分区的存储格式 = 表存储格式

分区存储格式:决定了该分区数据的实际存储格式

举个栗子

如果 db_name.tbl_name_1 一开始是 TextFile,并且新增了两个分区:part_1、part_2。那么 part_1 & part_2 这两个分区的存储格式都是 TextFile

后边我们修改了表存储格式,将其改成 ORC,并且新增了一个分区 part_3,那么 part_3 的存储格式为 ORC

此时表存储格式为 ORC,三个分区的存储格式如下表

分区名

存储格式

part_1

TextFile

part_2

TextFile

part_3

ORC

由此可见,即使是同一个分区表中的分区,其存储格式不一定全都一样

Hive & Spark 读取Hive表分区数据的差异

Hive读取分区数据,是依据分区实际存储格式来进行读写的。上个例子中:

  • 读取 part_3 将采用 ORC
  • 读取 part_1/part_2 将采用 TextFile
  • 新增 part_4 将是 ORC
  • 覆写/追加 part_2(INSERT OVERWRITE/INTO TABLE),part_2 的存储格式将会变成 ORC

Spark为了减少对 Hive Meta 的读取,默认表存储格式即分区存储格式。但Spark读取 part_1 时,将采用 ORC 的方式读取,然后会读取失败(part_1的数据实际上还是 TextFile)

三、修改表存储格式

ALTER TABLE <表名> SET FILEFORMAT <新格式,比如ORC>

修改表存储格式后:

  • 新增分区的存储格式为更新后的存储格式
  • 历史分区的存储格式仍为旧格式
  • Hive引擎可读历史分区
  • Spark引擎读取历史分区会报错(原因见上文)

四、重刷历史分区数据

重刷历史分区数据,将历史分区的存储格式修改成表最新存储格式

-- 必须使用 Hive 引擎进行数据重刷
INSERT OVERWRITE TABLE <表名> PARTITION(分区表达式)
SELECT
   xxx
  ,xxx
  ,xxx
FROM <表名>
WHERE 分区表达式