Spark에서 출력 디렉터리를 덮어 쓰는 방법


107

매분 데이터 세트를 생성하는 스파크 스트리밍 응용 프로그램이 있습니다. 처리 된 데이터의 결과를 저장 / 덮어 쓰기해야합니다.

org.apache.hadoop.mapred.FileAlreadyExistsException 데이터 세트를 덮어 쓰려고하면 실행이 중지됩니다.

Spark 속성을 설정 set("spark.files.overwrite","true")했지만 운이 없습니다.

Spark에서 파일을 덮어 쓰거나 미리 삭제하는 방법은 무엇입니까?


1
그래, 안타깝게도 0.9.0으로의 회귀라고 생각합니다. 내 대답 : 동의하십시오
samthebest

set("spark.files.overwrite","true")추가 된 파일에 대해서만 작동합니다.spark.addFile()
aiman

답변:


106

업데이트 : 사용 제안 Dataframes... .write.mode(SaveMode.Overwrite) ....

핸디 포주 :

implicit class PimpedStringRDD(rdd: RDD[String]) {
    def write(p: String)(implicit ss: SparkSession): Unit = {
      import ss.implicits._
      rdd.toDF().as[String].write.mode(SaveMode.Overwrite).text(p)
    }
  }

이전 버전의 경우

yourSparkConf.set("spark.hadoop.validateOutputSpecs", "false")
val sc = SparkContext(yourSparkConf)

1.1.0에서는 --conf 플래그와 함께 spark-submit 스크립트를 사용하여 conf 설정을 지정할 수 있습니다.

경고 (이전 버전) : @piggybox에 따르면 Spark에는 파일을 작성하는 데 필요한 파일 만 덮어 쓰는 버그 part-가 있으며 다른 파일은 제거되지 않은 상태로 유지됩니다.


29
For Spark 1.4:df.write.mode(SaveMode.Overwrite).parquet(path)
Ha Pham

Spark SQL의 경우 Core Spark에 대한 저장 모드를 정의 할 수있는 옵션이 있습니다. 겠습니까 정말 saveAsTextFile 및 다른 변환을위한 기능의 종류의 일부처럼
Murtaza Kanchwala

3
숨겨진 문제 : HDFS를 통해 전체 폴더를 지우는 @pzecevic의 솔루션과 비교하면이 접근 방식에서 Spark는 출력 폴더에서 동일한 파일 이름을 가진 부품 파일 만 덮어 씁니다. 이것은 대부분의 경우 작동하지만 폴더에 다른 Spark / Hadoop 작업의 추가 부품 파일과 같은 다른 파일이있는 경우 이러한 파일을 덮어 쓰지 않습니다.
piggybox

6
df.write.mode(mode: String).parquet(path)Where 모드를 사용할 수도 있습니다 . 문자열은 "overwrite", "append", "ignore", "error"일 수 있습니다.
rye

1
@avocado Yup 그렇게 생각합니다. Spark API는 모든 릴리스에서 점점 더 나빠집니다. : P
samthebest


27

매개 변수에 대한 문서는 spark.files.overwrite" SparkContext.addFile()대상 파일이 존재하고 그 내용이 소스의 내용과 일치하지 않을 때 추가 된 파일을 덮어 쓸지 여부"라고 말합니다 . 따라서 saveAsTextFiles 메서드에는 영향을주지 않습니다.

파일을 저장하기 전에 다음을 수행 할 수 있습니다.

val hadoopConf = new org.apache.hadoop.conf.Configuration()
val hdfs = org.apache.hadoop.fs.FileSystem.get(new java.net.URI("hdfs://localhost:9000"), hadoopConf)
try { hdfs.delete(new org.apache.hadoop.fs.Path(filepath), true) } catch { case _ : Throwable => { } }

Aas는 http://apache-spark-user-list.1001560.n3.nabble.com/How-can-I-make-Spark-1-0-saveAsTextFile-to-overwrite-existing-file-td6696에 설명되어 있습니다 . HTML


29
pyspark는 어떻습니까?
javadba

'write.mode (SaveMode.Overwrite)'를 사용하는 다음 대답은가는 길입니다
YaOg

hdfs는 여전히 이전 파일을 삭제하고 있으므로 들어오는 새 파일을 삭제할 수 있습니다.
Jake

25

로부터 pyspark.sql.DataFrame.save의 문서 (현재 1.3.1에서)을 지정할 수 있습니다 mode='overwrite'DataFrame을 저장할 때 :

myDataFrame.save(path='myPath', source='parquet', mode='overwrite')

나는 이것이 남은 파티션 파일도 제거한다는 것을 확인했습니다. 따라서 원래 10 개의 파티션 / 파일이 있다고 말했지만 6 개의 파티션 만있는 DataFrame으로 폴더를 덮어 쓴 경우 결과 폴더에는 6 개의 파티션 / 파일이 있습니다.

참고 항목 스파크 SQL 설명서를 모드 옵션에 대한 자세한 내용은.


2
사실이고 도움이되지만 DataFrame 특정 솔루션 spark.hadoop.validateOutputSpecs은 모든 Spark API에서 작동합니다.
samthebest

어떤 이유로 spark.hadoop.validateOutputSpecs1.3에서 나를 위해 작동하지 않았지만 이것은 작동합니다.
Eric Walker

1
@samthebest save(... , mode=경로를 사용하면 동일한 Spark 컨텍스트 내에서 한 파일 집합을 덮어 쓰고 다른 파일을 추가하는 등의 작업을 수행 할 수 있습니다. spark.hadoop.validateOutputSpecs컨텍스트 당 하나의 모드 로만 제한 하지 않겠습니까 ?
dnlbrky 2015 년

1
@dnlbrky OP는 추가를 요청하지 않았습니다. 내가 말했듯이 사실이고 유용하지만 불필요합니다. OP가 "어떻게 추가합니까"라고 물으면 전체 범위의 답변을 제공 할 수 있습니다. 하지만 그것에 대해 설명하지 말자. 또한 유형 안전성과 더 많은 검사 기능이있는 DataFrames의 Scala 버전을 사용하는 것이 좋습니다. 예를 들어 "덮어 쓰기"에 오타가있는 경우 해당 DAG가 평가 될 때까지 알 수 없습니다. 빅 데이터 작업에서 2 시간 후 !! Scala 버전을 사용하는 경우 컴파일러는 모든 것을 미리 확인합니다! 빅 데이터에 매우 멋지고 중요합니다.
samthebest 2015 년

15

df.write.mode('overwrite').parquet("/output/folder/path")파이썬을 사용하여 마루 파일을 덮어 쓰려면 작동합니다. 이것은 스파크 1.6.2에 있습니다. API는 이후 버전에서 다를 수 있습니다.


네, 내 요구 사항에 적합합니다 (Databricks)
Nick.McDermaid

4
  val jobName = "WordCount";
  //overwrite the output directory in spark  set("spark.hadoop.validateOutputSpecs", "false")
  val conf = new 
  SparkConf().setAppName(jobName).set("spark.hadoop.validateOutputSpecs", "false");
  val sc = new SparkContext(conf)

Spark 1 전용, 최신 버전 사용df.write.mode(SaveMode.Overwrite)
ChikuMiku

3

이 오버로드 된 버전의 저장 기능은 저에게 효과적입니다.

yourDF.save (outputPath, org.apache.spark.sql.SaveMode.valueOf ( "덮어 쓰기"))

위의 예는 기존 폴더를 덮어 씁니다. savemode는 다음 매개 변수도 사용할 수 있습니다 ( https://spark.apache.org/docs/1.4.0/api/java/org/apache/spark/sql/SaveMode.html ) :

Append : Append 모드는 DataFrame을 데이터 소스에 저장할 때 데이터 / 테이블이 이미 존재하는 경우 DataFrame의 내용이 기존 데이터에 추가되는 것을 의미합니다.

ErrorIfExists : 데이터 소스에 DataFrame를 저장할 때 데이터가 이미 존재하는 경우 ErrorIfExists 모드 수단은, 예외가 발생 될 것으로 예상된다.

Ignore : Ignore 모드는 DataFrame을 데이터 소스에 저장할 때 데이터가 이미 존재하는 경우 저장 작업이 DataFrame의 내용을 저장하지 않고 기존 데이터를 변경하지 않을 것으로 예상됨을 의미합니다.


1

고유 한 사용자 지정 출력 형식을 사용하려는 경우 RDD에서도 원하는 동작을 얻을 수 있습니다.

다음 클래스를 살펴보십시오 : FileOutputFormat , FileOutputCommitter

파일 출력 형식에는 출력 디렉토리가 존재하는지 확인하는 checkOutputSpecs라는 메소드가 있습니다. FileOutputCommitter에는 일반적으로 임시 디렉토리에서 최종 위치로 데이터를 전송하는 commitJob이 있습니다.

아직 확인할 수 없었지만 (자유로운 시간이 생기 자마자 할 것입니다) 이론적으로 : FileOutputFormat을 확장하고 checkOutputSpecs를 디렉터리에 예외를 발생시키지 않는 메서드로 재정의하면 이미 존재하고 사용자 정의 출력 커미터의 commitJob 메서드는 RDD로 원하는 동작을 달성 할 수있는 것보다 내가 원하는 로직 (예 : 일부 파일 재정의, 다른 파일 추가)을 수행합니다.

출력 형식은 saveAsNewAPIHadoopFile (실제로 파일을 저장하기 위해 호출되는 saveAsTextFile 메소드)에 전달됩니다. 그리고 출력 커미터는 응용 프로그램 수준에서 구성됩니다.


도움이된다면 FileOutputCommitter를 서브 클래 싱하는 것을 피할 것입니다. 이것은 무서운 코드입니다. Hadoop 3.0은 FileOutputFormat이 리팩토링 된 슈퍼 클래스 (PathOutputCommitter)의 다양한 구현을 취할 수있는 플러그인 지점을 추가합니다. 넷플릭스에서 S3 하나는 직장에서 갈등 해결 (실패, 삭제, 추가)를 확약하고, 분할 된 트리에 자리에서 쓰기, 만 업데이트 된 파티션에있는 것
stevel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.