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 。

相关推荐
闹小艾6 小时前
舞蹈教培机构小程序零基础制作开发全流程教程
大数据·小程序
阿乔外贸日记6 小时前
2026尼日利亚五项清关政策更新,拉高能源装备进口综合成本
大数据·人工智能·搜索引擎·智能手机·云计算·能源
暴躁小师兄数据学院6 小时前
【AI大数据工程师特训笔记】第12讲:表分区与索引
大数据·笔记·sql·postgresql
侃谈科技圈6 小时前
破除数据中台落地困境:2026数据治理平台差异化能力与选型决策指南
大数据·人工智能
Elastic 中国社区官方博客7 小时前
Elasticsearch DiskBBQ:使用原生 SIMD Blocks 实现快 40% 的向量评分计算
大数据·人工智能·elasticsearch·搜索引擎·ai·全文检索·diskbbq
暴躁小师兄数据学院8 小时前
【AI大数据工程师特训笔记】第16讲:大数据环境安装
大数据·hadoop·笔记·flink·spark·database
豆豆8 小时前
垂直行业门户网站搭建解决方案与落地实操指南
大数据·cms·pageadmin·自定义模型·垂直门户·行业建站·站群建设
Elastic 中国社区官方博客8 小时前
Kibana:使用 AI Chat 及 MCP 轻松创建 AI 原生仪表板
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·信息可视化
Thomas_YXQ9 小时前
Unity无GC读取图片与网格完整方案
大数据·人工智能·unity·微信·产品运营
1892280486110 小时前
NV023固态MT29F16T08GWLCEJ9-QBES:C
大数据·服务器·人工智能·科技·缓存