分区信息无法查到的问题

Hive 分区信息丢失:HDFS 上传数据后查不到?MSCK REPAIR TABLE 一键修复

在 Hive 分区表的使用中,有一个非常常见的坑:

  1. 你在 HDFS 上手动建了一个分区目录,比如 date=20210415
  2. 把数据文件传进去了
  3. 去 Hive 里 SHOW PARTITIONS,看不到这个分区
  4. SELECT * FROM 表 WHERE date='20210415',也查不到数据

数据明明在 HDFS 上,Hive 就是看不见。

问题现象:数据传上去了,Hive 查不到

假设你有一个分区表 test_partitioned,按 date 分区。

你用 HDFS 命令手动创建了分区目录并上传了数据:

hdfs dfs -mkdir /user/hive/warehouse/study_hive.db/test_partitioned/date=20210415
hdfs dfs -put data.txt /user/hive/warehouse/study_hive.db/test_partitioned/date=20210415/

HDFS 上已经有这个目录了:

hdfs分区文件夹

去 Hive 里查看:

SHOW PARTITIONS test_partitioned;
-- 结果只有 date=20210413 和 date=20210414
-- date=20210415 没出现

hive元数据分区

查询也查不到:

SELECT * FROM test_partitioned WHERE date='20210415';
-- 返回空

原因:元数据没同步

Hive 的分区信息存在两个地方:

存储位置 存什么 谁写的
HDFS 分区目录 + 数据文件 HDFS 命令 / LOAD DATA
Metastore(元数据) 分区记录 Hive 命令(LOAD / INSERT)

通过 Hive 的 LOAD DATAINSERT 导入数据时,Hive 会自动写 Metastore。

通过 HDFS 直接上传时,只有 HDFS 上有目录,Metastore 里没有记录。

Hive 查询时先查 Metastore——里面没有 date=20210415 这条记录,就认为这个分区不存在。

修复:用 MSCK REPAIR TABLE

一句话把缺失的分区补回来:

MSCK REPAIR TABLE test_partitioned;

执行结果类似:

Partitions not in metastore: test_partitioned:date=20210415
Repair: Added partition to metastore test_partitioned:date=20210415

再去 Hive 里看:

SHOW PARTITIONS test_partitioned;
-- 现在有了:date=20210413, date=20210414, date=20210415

查询也能查到数据了。

MSCK REPAIR TABLE 做了什么:

  1. 扫描表在 HDFS 上的根目录
  2. 找到所有符合 分区列=值 格式的子目录
  3. 跟 Metastore 里的记录做对比
  4. 把缺失的分区加到 Metastore 里

二级分区同样适用

如果你的表是二级分区(比如 date + hour):

/user/hive/warehouse/.../date=20210415/hour=10/

同样适用:

MSCK REPAIR TABLE test_partitioned_2;

会递归扫描所有二级目录,把缺失的 date=xxx/hour=xxx 全补上。

其他修复方式:手动 ADD PARTITION

如果分区数量很少,也可以手动加:

ALTER TABLE test_partitioned ADD PARTITION (date='20210415');

MSCK REPAIR TABLE 适合一次性修一批,ALTER TABLE ADD PARTITION 适合只加一两个。

预防:别让问题再发生

方法1:用 Hive 命令导入,别用 HDFS 直接传

-- 推荐:用 LOAD DATA,自动同步元数据
LOAD DATA LOCAL INPATH '/tmp/data.txt'
INTO TABLE test_partitioned
PARTITION (date='20210415');

方法2:如果必须用 HDFS 上传,上传后立即修复

写脚本自动处理:

# 上传数据
hdfs dfs -put data.txt /warehouse/test_partitioned/date=20210415/

# 立即修复分区
hive -e "MSCK REPAIR TABLE test_partitioned;"

方法3:定时任务兜底

如果分区是系统自动生成的(比如每天一个),可以加一个定时任务,每天跑一次修复:

# crontab: 每天凌晨 3 点执行修复
0 3 * * * hive -e "MSCK REPAIR TABLE test_partitioned;" >> /var/log/repair.log 2>&1

常见问题

1. MSCK REPAIR TABLE 执行很慢怎么办?

分区数量太多的时候(比如上万个),扫描目录会慢。

可以分批次处理,或者调整批量大小:

SET hive.msck.repair.batch.size=1000;
MSCK REPAIR TABLE test_partitioned;

2. 修复后还是查不到数据?

检查数据文件格式跟表定义是否一致——分隔符对不对、列数对不对。

3. 外部表也适用吗?

适用。内部表和外部表都会遇到同样的问题,MSCK REPAIR TABLE 两种表都能修。