hadoop冷热数据分离

将Hive表的历史数据从三副本改为单副本,以节省存储空间

对于历史数据的副本数调整,修改全局配置后(hdfs-site.xml中的dfs.replication默认副本数)只影响设置生效后新写入的数据。历史数据的副本数不会改变,必须手动执行命令来降低。另外只是对历史数据进行副本减少,近期数据还是要保持三副本。

sql 复制代码
create table tmp.tmp_20260513(
client_id string comment '客户号',
status int comment '状态'
) comment '客户信息'
partitioned by (etl_date int comment '分区日期');

show create table tmp.tmp_20260513;
--CREATE TABLE `tmp`.`tmp_20260513`(
--`client_id` string COMMENT '客户号',
--`status` int COMMENT '状态')
--COMMENT '客户信息'
--PARTITIONED BY (
--`etl_date` int COMMENT '分区日期')
--ROW FORMAT SERDE
--'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
--STORED AS INPUTFORMAT
--'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
--OUTPUTFORMAT
--'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
--LOCATION
--'hdfs://HDFS78000003/usr/hive/warehouse/tmp.db/tmp_20260513'
--TBLPROPERTIES (
--'transient_lastDdlTime'='1778721013')

insert overwrite table tmp.tmp_20260513 partition(etl_date=20260513)
select '11234875' as client_id,1 as status;
insert into table tmp.tmp_20260513 partition(etl_date=20260513)
select '11234876' as client_id,1 as status;
select * from tmp.tmp_20260513;
-- client_id	status	etl_date
-- 11234875	1	    20260513
-- 11234876	1	    20260513

1 查看块副本数

powershell 复制代码
hdfs fsck /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513 -files -blocks -locations 
/usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513/000000_0 640 bytes, replicated: replication=3, 1 block(s):  OK
0. BP-1541143118-172.18.206.123-1735650027318:blk_1235574560_161842301 len=640 Live_repl=3  [DatanodeInfoWithStorage[172.18.206.139:4001,DS-f530050e-a0ba-45c5-95b2-9bcf77fdc740,DISK], DatanodeInfoWithStorage[172.18.206.141:4001,DS-e776bcbb-6a79-4389-a6f7-9bd95dea743c,DISK], DatanodeInfoWithStorage[172.18.206.140:4001,DS-8aa75b83-28f8-4dd6-9e6c-f3cd836183ac,DISK]]

/usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513/000000_0_copy_1 640 bytes, replicated: replication=3, 1 block(s):  OK
0. BP-1541143118-172.18.206.123-1735650027318:blk_1235575151_161842892 len=640 Live_repl=3  [DatanodeInfoWithStorage[172.18.206.133:4001,DS-ed3ce38d-f3c9-4933-8903-d17165a540fe,DISK], DatanodeInfoWithStorage[172.18.206.142:4001,DS-3719e56a-2a38-47fb-81bf-df7517d1de47,DISK], DatanodeInfoWithStorage[172.18.206.127:4001,DS-05f6611e-1173-4334-94a5-d3fb9907c80d,DISK]]

The filesystem under path '/usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513' is HEALTHY
· 路径:/usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513
· 文件数:2个小文件(每个640字节)
· 副本数:replication=3(每个块都分布在3个不同的DataNode上,且存储介质都是DISK)
· 状态:HEALTHY,无缺失/损坏块

hdfs dfs -ls /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513 --2个640字节文件
Found 2 items
-rw-r--r--   3 san.zhang supergroup        640 2026-05-14 09:13 /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513/000000_0
-rw-r--r--   3 san.zhang supergroup        640 2026-05-14 09:15 /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513/000000_0_copy_1

hdfs dfs -du -h /usr/hive/warehouse/tmp.db/tmp_20260513 ;
1.3 K 3.8 K /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513

2 有小文件,需要合并减少磁盘占用

sql 复制代码
SET hive.exec.dynamic.partition.mode=nonstrict;
SET hive.merge.mapfiles=true;
SET hive.merge.mapredfiles=true;
SET hive.merge.size.per.task=268435456;   -- 256MB,目标文件大小
SET hive.merge.smallfiles.avgsize=16777216; -- 平均文件小于16MB则触发合并

INSERT OVERWRITE TABLE tmp.tmp_20260513 PARTITION (etl_date='20260513')
SELECT client_id,status FROM tmp.tmp_20260513 WHERE etl_date='20260513';

hdfs dfs -ls /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513 --合完以后变成1个665字节文件
Found 1 items
-rw-r--r--   3 san.zhang supergroup        665 2026-05-14 09:57 /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513/000000_0

3 修改hdfs文件副本

powershell 复制代码
hdfs dfs -setrep -R -w 1 /user/hive/warehouse/[database_name].db/[table_name]/[partition]
· -R:对所有子目录和文件递归生效。
· -w:命令会等待直到整个集群的副本调整完成再退出。
· 强烈建议按分区或目录逐个处理,避免长时间运行的大任务影响集群性能。

示例:将所有 dt 在 2024-05-13 及之前的分区改为 1 副本

powershell 复制代码
hive -e "use mydb; show partitions my_table;" | grep -E "dt=[0-9]{4}-[0-9]{2}-[0-9]{2}" | while read partition; do
   dt_val=$(echo $partition | cut -d'=' -f2)
   # 比较日期是否 <= 2024-05-13(一年前的今天)
   if [[ "$dt_val" < "2024-05-14" ]]; then
       hdfs_path="/user/hive/warehouse/mydb.db/my_table/$partition"
       echo "降副本: $hdfs_path"
       hdfs dfs -setrep -R -w 1 "$hdfs_path"
   fi
done
powershell 复制代码
# 改为两副本
hdfs dfs -setrep -R -w 2 /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513
hdfs dfs -ls /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513
Found 1 items
-rw-r--r--   2 san.zhang supergroup        665 2026-05-14 09:57 /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513/000000_0
# 改为一副本
hdfs dfs -setrep -R -w 1 /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513
hdfs dfs -ls /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513
Found 1 items
-rw-r--r--   1 san.zhang supergroup        665 2026-05-14 09:57 /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513/000000_0

4 验证查看块副本数

powershell 复制代码
hdfs fsck <分区路径> -files -blocks -locations 
hdfs fsck /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513 -files -blocks -locations 
/usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513/000000_0 665 bytes, replicated: replication=1, 1 block(s):  OK
0. BP-1541143118-172.18.206.123-1735650027318:blk_1235588796_161856537 len=665 Live_repl=1  [DatanodeInfoWithStorage[172.18.206.136:4001,DS-abad2fb5-a6c7-4d14-9c67-40523da553e3,DISK]]

The filesystem under path '/usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513' is HEALTHY
· 路径:/usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513
· 文件数:1个小文件(每个665字节)
· 副本数:replication=1(每个块都分布在1个不同的DataNode上,且存储介质都是DISK)
· 状态:HEALTHY,无缺失/损坏块

5 合并小文件的方法(按推荐顺序)

方法一:Hive Concatenate(仅支持ORC/Parquet格式)

如果表文件格式是ORC或Parquet,可以直接合并:

sql 复制代码
ALTER TABLE tmp.tmp_20260513 
PARTITION (etl_date='20260513') 
CONCATENATE;

· 优点:简单,不会产生临时数据,原地合并。

· 限制:只支持ORC/Parquet;合并后文件大小会接近HDFS块大小(通常128MB/256MB),但无法精确控制。

方法二:INSERT OVERWRITE(通用,任意文件格式)

无论文件格式是什么(TextFile、SequenceFile等),都可以通过重写分区来合并:

sql 复制代码
SET hive.exec.dynamic.partition.mode=nonstrict;
SET hive.merge.mapfiles=true;
SET hive.merge.mapredfiles=true;
SET hive.merge.size.per.task=268435456;   -- 256MB,目标文件大小
SET hive.merge.smallfiles.avgsize=16777216; -- 平均文件小于16MB则触发合并

INSERT OVERWRITE TABLE tmp.tmp_20260513 PARTITION (etl_date='20260513')
SELECT client_id,status FROM tmp.tmp_20260513 WHERE etl_date='20260513';

· 原理:启动一个MapReduce或Tez作业读取原数据,写入时自动合并成设定大小的文件。

· 注意:执行期间原分区数据会被覆盖,请确保没有并发写入。如果数据重要,可先备份分区到临时目录。

方法三:使用Hive小文件合并工具(Hive 3.0+)

使用 hive --service merge 命令:

powershell 复制代码
hive --service merge \
  --table tmp.tmp_20260513 \
  --partition etl_date=20260513 \
  --size 256 \
  --output /tmp/merged_output

(具体参数视版本而定,不如方法二常用)

方法四:Hadoop Archive(HAR)

将小文件打包成HAR文件,减少NameNode内存占用,但查询性能可能下降(需特殊URL访问)。不推荐用于后续频繁分析。

powershell 复制代码
hadoop archive -archiveName data.har -p /usr/hive/warehouse/tmp.db/tmp_20260513/etl_date=20260513 /output/dir

6 注意事项与风险

· 数据丢失风险:单副本意味着一旦存储该数据的节点损坏,数据将彻底丢失。操作前务必确认这些数据可以从原始数据源回溯或已备份至冷存储(如OSS)再操作。

· 读取性能影响:HDFS的"短路读取"特性在本地副本可用时性能最佳。降为单副本后,若读取任务被调度到非数据所在节点,可能引发额外的跨节点读取网络开销。

· Block复制风暴:使用-setrep -w时,NameNode会调度DataNode立即开始删除多余副本,这可能产生较大的集群内部网络IO。

· 小文件陷阱:若表中存在大量小文件(远小于128MB),降低副本数的收益有限。建议先合并小文件。

· 新写入的分区依然会是三副本(取决于集群默认副本设置),除非手工调整或提前设置set dfs.replication=1;。

· 恢复全局设置:若希望恢复默认设置,将该值改回3,并再次运行hdfs dfs -setrep -R -w 3 。

相关推荐
Raas1004 小时前
MAI Gateway(魔芋企业级AI网关)技术揭秘:AI网关支持哪些模型?从原理到落地
大数据·人工智能·网关·gateway·mai gateway·企业级产品
YangYang9YangYan7 小时前
2026 校招商品分析岗位 JD 拆解,核心指标、工具与面试考点
大数据·数据库·数据分析
大大大大晴天7 小时前
OpenMetadata VS DataHub VS Atlas VS Gravitino
大数据
Qyr9910 小时前
2026全球汽车碳刷行业发展全景分析报告
大数据
蓝速科技11 小时前
便民服务大厅 AI 数字人一体机场景适配与落地指南丨蓝速科技
大数据·网络·数据结构·人工智能·自然语言处理·数据分析·运维开发
精益数智工坊11 小时前
云计算环境数据怎么同步?云计算集成方案有哪些?
大数据·人工智能·数据挖掘·数据可视化
huashengzsj12 小时前
什么是DMS经销商管理系统?国内经销商管理系统有哪些品牌
大数据
IT毕设梦工厂13 小时前
计算机毕业设计选题推荐:基于大数据的草鱼价格分析与可视化|毕业设计选题|计算机毕设|选题推荐|毕设指导|项目定制|源码|高质量项目
大数据·hadoop·python·数据挖掘·数据分析·课程设计·大数据毕设项目
辛迪聊物业数字化13 小时前
智慧社区物业管理软件新手部署与实操指南
大数据·php
字节跳动数据平台14 小时前
模型再强,为什么 Demo 还是进不了生产?
大数据