Apache spark spark csv赢得';是否不将数据帧保存到文件?

Apache spark spark csv赢得';是否不将数据帧保存到文件?,apache-spark,spark-csv,Apache Spark,Spark Csv,dataFrame.coalesce(1).write().save(“path”)有时只写入_SUCCESS和_SUCCESS.crc文件,即使在非空输入上也没有预期的*.csv.gzdataFrame 文件保存代码: private static void writeCsvToDirectory(数据集数据帧,路径目录){ 数据帧合并(1) .write() .格式(“csv”) .选项(“标题”、“正确”) .option(“分隔符”、“\t”) .option(“codec”,“org.

dataFrame.coalesce(1).write().save(“path”)
有时只写入_SUCCESS和_SUCCESS.crc文件,即使在非空输入上也没有预期的*.csv.gz
dataFrame

文件保存代码:

private static void writeCsvToDirectory(数据集数据帧,路径目录){
数据帧合并(1)
.write()
.格式(“csv”)
.选项(“标题”、“正确”)
.option(“分隔符”、“\t”)
.option(“codec”,“org.apache.hadoop.io.compress.gzip代码”)
.mode(SaveMode.Overwrite)
.save(“文件://“+目录);
}
文件获取代码:

静态路径getTemporaryCsvFile(路径目录)引发IOException{
字符串glob=“*.csv.gz”;
try(DirectoryStream=Files.newDirectoryStream(directory,glob)){
返回stream.iterator().next();
}捕获(无接触元素例外e){
抛出新的运行时异常(getNoSuchElementExceptionMessage(目录,glob),e);
}
}
文件获取错误示例:

java.lang.RuntimeException:directory/tmp/temp5889805853850415940不包含带有glob*.csv.gz的文件。目录列表:
/tmp/TEMP5880535850415940/_成功,
/tmp/temp5889805853850415940/\u SUCCESS.crc
我依赖于这个期望,有人能解释一下为什么它是这样工作的吗

输出文件应该(逻辑上必须)至少包含标题行和一些数据行。但他根本不存在

这一评论有点误导。根据Github上的代码,只有当数据帧为空时才会发生这种情况,并且不会生成
SUCCESS
文件。考虑到这些文件存在-Dataframe不是空的,并且会触发代码中的
writeCsvToDirectory

我有几个问题:

  • 你的Spark工作完成时没有错误吗
  • SUCCESS
    文件的时间戳是否得到更新
我的两个主要嫌疑犯是:

  • coalesce(1)
    -如果您有大量数据,这可能会失败
  • SaveMode.Overwrite
    -我感觉这些成功文件位于以前运行的文件夹中

  • 我自己的解决方案解决了这个问题

    我将
    .save(“文件:/”
    替换为
    hadoopFileSystem.copyToLocalFile

    问题是,
    .save(“文件://
    预期仅适用于
    SparkSession.builder().master(“本地”)
    ,其中
    hdfs://
    由master的
    文件://
    模拟

    理论上我可能是错的,但它是有效的

    静态路径writeCsvToTemporaryDirectory(数据集数据帧)引发IOException{
    字符串temporaryDirectoryName=getTemporaryDirectoryName();
    writeCsvToDirectory(数据帧、临时目录名、sparkContext);
    返回path.get(temporaryDirectoryName);
    }
    静态void writeCsvToDirectory(数据集数据帧、字符串目录)引发IOException{
    数据帧合并(1)
    .write()
    .选项(“标题”、“正确”)
    .option(“分隔符”、“\t”)
    .option(“codec”,“org.apache.hadoop.io.compress.gzip代码”)
    .mode(SaveMode.Overwrite)
    .csv(目录);
    FileSystem hadoopFileSystem=FileSystem.get(sparkContext.hadoopConfiguration());
    hadoopFileSystem.copyToLocalFile(true,
    新的org.apache.hadoop.fs.Path(目录),
    新的org.apache.hadoop.fs.Path(目录));
    }
    静态路径getTemporaryCsvFile(路径目录)引发IOException{
    字符串glob=“*.csv.gz”;
    try(DirectoryStream=Files.newDirectoryStream(directory,glob)){
    返回stream.iterator().next();
    }捕获(无接触元素例外e){
    抛出新的运行时异常(getNoSuchElementExceptionMessage(目录,glob),e);
    }
    }
    Path temporaryDirectory=writeCsvToTemporaryDirectory(数据帧);
    Path temporaryFile=DataFrameIOUtils.getTemporaryCsvFile(临时目录);
    试一试{
    返回otherStorage.upload(临时文件、名称、字段).join();
    }捕获(中断异常|执行异常e){
    抛出新的运行时异常(e);
    }最后{
    移除临时目录(临时目录);
    }
    
    您选择编写csv文件取决于您的存储空间。 如果您在hdfs上写入,一切都正常。但无论何时您决定在本地文件系统中写入,您必须注意,不会在驱动程序本地文件系统中写入任何内容,并且您的数据将在工作人员的文件系统中,您应该在工作人员的存储中找到它们

    两种解决方案:

  • 在本地模式下运行Spark
  • 设置您可以通过
    --master local[10]
    config提交作业的主本地[核心数量]

  • 在分布式文件系统中写入

  • 将您的数据写入分布式文件系统,如s3、hdfs等

    请随意猜测=)我也会很高兴阅读它,而不仅仅是完整的解决方案和对我的问题的全面分析。您知道输出文件是否包含记录吗?从.\u Success到\u Success的移动至少表明了写入操作(从逻辑上讲)生成临时文件并将其移动到其最终存放位置。输出文件(必须按逻辑)应至少包含标题行和一些数据行。但在写入语句期间,该文件根本不存在,还包括println(“#####输出记录数:“+inputDF.count+”#####”)。在输出日志上运行此“cat output.log | grep#######'。这将能够告诉我们问题是您试图写入的inputDF是否为空。@afeldman inputDF在设计上不能为空。为了简洁起见,我省略了一些细节。您可以在>上阅读完整的类实现。如果您有大量数据,这可能会失败s大约0.5GB。>我有一种感觉,这些成功文件位于以前运行的文件夹中。这是显而易见的,但我已经很久没有注意到了。