如何使用HIVE按年月拆分文本文件并写入HDFS对应目录
方案推荐及效率对比
最优实现:Hive动态分区(操作最简单、效率最高)
你之前的方案耗时极长的核心原因是每次查询单个月份都要全量扫描一次所有原始数据,月份越多扫描次数越多,冗余开销极大。用Hive动态分区只需要全量扫描一次原始数据,自动按年月拆分到对应目录,完全不需要逐个月份执行:
- 第一步:创建带年月分区的目标Hive外部表,存储路径指向你要最终存放数据的HDFS根目录:
CREATE EXTERNAL TABLE IF NOT EXISTS split_target ( -- 此处字段和你之前创建的原始表字段完全一致即可 col1 string, col2 int, -- 其他字段依次填写 dt string ) PARTITIONED BY (year int, month int) LOCATION '/你期望的HDFS根存储路径/';
- 第二步:开启动态分区配置,单次执行插入即可完成全量数据拆分:
-- 开启动态分区必填配置 set hive.exec.dynamic.partition=true; set hive.exec.dynamic.partition.mode=nonstrict; set hive.exec.max.dynamic.partitions.pernode=1000; -- 一次插入完成全量拆分,自动生成对应年月的分区目录 INSERT OVERWRITE TABLE split_target PARTITION(year, month) SELECT *, YEAR(dt) AS year, MONTH(dt) AS month FROM 存储原始7份文件的Hive表名;
执行完成后,HDFS的/你期望的HDFS根存储路径/下会自动生成year=2015/month=1这类格式的子目录,如果你需要2015/1这种不带前缀的目录名,直接用hdfs dfs -mv批量重命名即可。
其他方案对比
- 命令行处理:7份文件共700万行属于极小数据量,如果原始文件在本地,用awk拆分后上传HDFS的速度也很快,但如果原始文件已经存放在HDFS上,需要先下载到本地再处理上传,反而多了跨节点IO开销,整体效率低于分布式处理方案。
- Java Jar调用:不管是自定义MapReduce还是Spark Jar,本质和Hive动态分区的分布式处理逻辑一致,效率没有明显差异,但需要自行开发打包,操作成本远高于直接写SQL,没有必要选择。
轻量快速方案
如果你不想操作Hive表,也可以直接用Spark Shell一行命令完成拆分,路径格式可以自定义更灵活:
// 此处假设原始文本用\t分隔,日期字段为第3列(索引从0开始为2),可根据实际调整分隔符和字段索引 spark.read.text("/原始文件HDFS路径/*") .select($"value", split($"value", "\\t")(2).cast("date").alias("date_col")) .write .partitionBy(year($"date_col"), month($"date_col")) .text("/输出HDFS根路径")
内容的提问来源于stack exchange,提问作者user10384204
相关产品推荐
相关产品推荐

