分区信息无法查到的问题
Hive 分区信息丢失:HDFS 上传数据后查不到?MSCK REPAIR TABLE 一键修复
在 Hive 分区表的使用中,有一个非常常见的坑:
- 你在 HDFS 上手动建了一个分区目录,比如
date=20210415 - 把数据文件传进去了
- 去 Hive 里
SHOW PARTITIONS,看不到这个分区 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 上已经有这个目录了:

去 Hive 里查看:
SHOW PARTITIONS test_partitioned;
-- 结果只有 date=20210413 和 date=20210414
-- date=20210415 没出现

查询也查不到:
SELECT * FROM test_partitioned WHERE date='20210415';
-- 返回空
原因:元数据没同步
Hive 的分区信息存在两个地方:
| 存储位置 | 存什么 | 谁写的 |
|---|---|---|
| HDFS | 分区目录 + 数据文件 | HDFS 命令 / LOAD DATA |
| Metastore(元数据) | 分区记录 | Hive 命令(LOAD / INSERT) |
通过 Hive 的 LOAD DATA 或 INSERT 导入数据时,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 做了什么:
- 扫描表在 HDFS 上的根目录
- 找到所有符合
分区列=值格式的子目录 - 跟 Metastore 里的记录做对比
- 把缺失的分区加到 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 两种表都能修。