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 分区表达式