Apache spark Spark dataframe saveAsTable vs save

Apache spark Spark dataframe saveAsTable vs save,apache-spark,spark-dataframe,orc,Apache Spark,Spark Dataframe,Orc,我正在使用spark 1.6.1,并试图将数据帧保存为orc格式 我面临的问题是保存方法非常慢,每个执行器上的50M orc文件大约需要6分钟。 这就是我保存数据帧的方式 dt.write.format("orc").mode("append").partitionBy("dt").save(path) dt.write.format("orc").mode("append").partitionBy("dt").saveAsTable(tableName) 我尝试将saveAsTable应

我正在使用spark 1.6.1,并试图将数据帧保存为orc格式

我面临的问题是保存方法非常慢,每个执行器上的50M orc文件大约需要6分钟。 这就是我保存数据帧的方式

dt.write.format("orc").mode("append").partitionBy("dt").save(path)
dt.write.format("orc").mode("append").partitionBy("dt").saveAsTable(tableName)
我尝试将saveAsTable应用到一个同样使用orc格式的配置单元表中,速度似乎快了20%到50%,但这种方法也有自己的问题——当任务失败时,由于文件已经存在,重试总是会失败。 这就是我保存数据帧的方式

dt.write.format("orc").mode("append").partitionBy("dt").save(path)
dt.write.format("orc").mode("append").partitionBy("dt").saveAsTable(tableName)
保存方法如此缓慢有什么原因吗?
我做错什么了吗?

问题是由于按方法分区造成的。PartitionBy读取指定列的值,然后为分区列的每个值分离数据。
尝试在不使用分区方式的情况下保存它,会有显著的性能差异。

请参阅我前面关于基数和分区方式的评论

如果您真的想对它进行分区,而它只是一个50MB的文件,那么可以使用

dt.write.format(“orc”).mode(“append”).repartition(4).saveAsTable(tableName)

重新分区将创建4个大致相等的分区,而不是对dt列进行分区,这可能会导致编写大量orc文件


选择4个分区有点随意。对这样的小文件进行分区,不会给性能/并行化带来太多好处。读取更多文件的开销是不值得的。

我需要对数据进行分区,因此这不是一个选项。我认为这是一个有效的观点。什么是dt?这是一个适合分区的列吗?如果基数很高,那么它可能不合适。例如,如果您对数据帧的每一行使用不同的值,那么这将导致太多分区。所有这些文件I/O的开销都是不值得的。6分钟对于编写5000万个文件来说并不是那么慢。听起来好像有很多文件!每个有多大?有多少遗嘱执行人?如果是每行一个文件,那就太多了。如果它们适合您的存储系统,并且在典型查询中使用的节点/执行器的数量可能为5000万,但我对此表示怀疑。如果这5000万个文件中的每一个都是1G,那么大约是47 PB,所以我对此表示怀疑。如果每个都是1MB,那么它是47 TB,我建议文件太小,无法有效地查询表。总数据量是多少?实际上是50兆文件。就像,它只是一个50MB的文件?如果它只是一个小文件,那么对它没有多大意义。可能是dt字段的基数太大,最终会为每一行创建分区。例如,如果是时间戳/日期时间,如“2017-01-01 14:52:22”,则每秒钟将发生一次分区,这将为每个分区写入一个orc文件。50MB可能是一个小文件,但它可能是许多具有不同时间戳的行。e、 g.如果每行约为8K,则约为6400行,这是大量的文件I/O。