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 。

相关推荐
skilllite作者1 小时前
Evotown——开启本地化、可验证的AI智能体进化新时代
人工智能·分布式·安全·搜索引擎·agentskills
SelectDB1 小时前
Agent 应用范式下,企业数据基础设施如何演进?
大数据·数据库·数据分析
vx_biyesheji00041 小时前
计算机毕业设计:Python医疗数据分析平台 Flask框架 数据分析 可视化 医疗大数据 用户画像(建议收藏)✅
大数据·python·深度学习·数据分析·django·flask·课程设计
科技小花2 小时前
2026 年度生成式引擎优化(GEO)标杆产品:百分点科技 Generforce 的差异化路径
大数据·人工智能·科技·geo·ai搜索
研华科技Advantech2 小时前
新一代工业控制开发平台:破解三大痛点
大数据
敏君宝爸2 小时前
RabbitMQ多线程消费与死信队列方案
分布式·rabbitmq
tsyjjOvO2 小时前
深入浅出 RabbitMQ:从原理到实战
分布式·rabbitmq
爱吃苹果的梨叔2 小时前
2026年分布式坐席系统技术指南:从KVM延长到全IP坐席协作
分布式·网络协议·tcp/ip
幂律智能2 小时前
Prompt不是提问,而是任务定义
大数据·人工智能·prompt