Spark通过PySpark加载S3数据至Hive表时源文件被删除的问题
问题解析与解决方案
为什么S3源文件会被删除?
Spark/Hive的LOAD DATA INPATH命令,针对分布式存储路径(比如S3、HDFS)时,默认执行的是移动操作而非复制操作——它会把源文件从S3的原路径移动到Hive表对应的存储目录(通常是HDFS或你配置的表存储路径),所以原路径下的文件会消失,看起来像是被删除了。这是设计语义,目的是避免分布式存储上的冗余数据,只是官方文档没有特别明确强调这一点。
为什么加LOCAL子句会报错?
LOCAL子句是用来指定Spark Driver所在机器的本地文件系统路径的,当你给LOAD DATA LOCAL INPATH传入S3路径时,Spark会去本地磁盘找这个文件,自然找不到,所以抛出文件查找错误。
保留S3源文件的解决方案
如果想保留S3上的源文件,不要用LOAD DATA,改用INSERT INTO结合文件读取的方式,这会执行复制操作:
方式1:PySpark DataFrame API
# 读取S3上的文本文件 df = spark.read.text("s3://bucket/kv1.txt") # 根据文本格式解析字段(假设是逗号分隔的key,value) df = df.selectExpr( "cast(split(value, ',')[0] as int) as key", "split(value, ',')[1] as value" ) # 覆盖写入Hive表 df.write.mode("overwrite").insertInto("src")
方式2:Spark SQL
INSERT OVERWRITE TABLE src SELECT cast(split(value, ',')[0] as int) as key, split(value, ',')[1] as value FROM text.`s3://bucket/kv1.txt`
补充说明
如果一定要用LOAD DATA命令,又想保留源文件,只能先手动把S3上的源文件复制到另一个S3路径,再对复制后的路径执行LOAD DATA,但这种方式多了额外的复制步骤,不如直接用INSERT的方式高效。
内容的提问来源于stack exchange,提问作者Geruh
相关产品推荐
相关产品推荐

