Spark删除外部表是否删路径/数据?代码执行路径被覆盖求助
关于Spark外部表删除与数据追加问题的解答
问题1:Spark中删除外部表时,是否会删除存储路径或对应数据?
简单来说,默认情况下不会。Spark中的表分为两类,删除行为差异很大:
- 内部表(Managed Table):删除时会同时清除元数据(Hive Metastore里的表定义)和底层存储的实际数据。
- 外部表(External Table):默认删除操作只会移除元数据,底层存储路径里的数据会完整保留下来。
不过有个例外:如果使用DROP TABLE ... PURGE命令删除外部表(Spark 3.0+或兼容的Hive版本支持),则会直接删除元数据和对应数据,跳过回收站环节。所以如果想保留数据,删除外部表时不要加PURGE参数。
问题2:为何使用SaveMode.Append仍会覆盖存储路径?
看你的代码,每次执行前都会先跑spark.sql("drop table if exists Staging.test_partiton_drop"),这就是问题的核心:
SaveMode.Append的生效前提是表已存在:当你删除表后,再次调用saveAsTable时,表是不存在的,此时Append模式的行为等价于Create模式——Spark会创建新的外部表,而默认情况下,创建外部表时如果指定的存储路径已有数据,Spark会自动清理路径中的现有内容(不同版本行为可能略有差异,但你的环境明显触发了这个逻辑)。- 非数据文件的干扰:你在代码最后创建了
/_REPLICATION.DONE文件,Spark重新创建表时,可能会判定路径中的非Parquet文件属于无效数据,进而触发整个路径的清理。
解决办法:
- 去掉前置的删表操作:如果你的目标是持续向表中追加数据,完全不需要每次删除表。保留表的元数据,直接执行写入并使用
SaveMode.Append,Spark会自动将新数据追加到现有路径,同时更新分区信息。修改后的核心代码片段:// 移除这行删表代码:spark.sql("drop table if exists Staging.test_partiton_drop") val df = Seq(("Aravind", "DIP"), ("Karthik", "DTP")).toDF("name", "dept") .withColumn("hdp_load_dt", current_date()).withColumn("hdp_load_hr", from_unixtime(unix_timestamp(), "HH")) var partitionBySeq = Seq("hdp_load_dt", "hdp_load_hr") df .write.partitionBy(partitionBySeq:_*) .format("parquet") .mode(SaveMode.Append) .option("path", "/krnoir/streaming_test") .option("compression", "snappy") .saveAsTable("Staging.test_partiton_drop") - 若必须删表,保留路径数据:如果有特殊需求必须删除表,那么重新创建表时需要添加配置,允许Spark在非空路径创建外部表。可以在SparkSession初始化时加入:
同时建议不要在表的存储路径中放置非数据文件(比如.config("spark.sql.legacy.allowCreatingManagedTableUsingNonemptyLocation", "true")/_REPLICATION.DONE),避免Spark处理数据时触发意外的清理或读取错误。
内容的提问来源于stack exchange,提问作者Neo
相关产品推荐
相关产品推荐

