2016-07-22 28 views
1

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

我面临的问题是保存方法非常慢,每个执行程序需要大约6分钟50M的兽人文件。 这是我现在的储蓄数据帧

dt.write.format("orc").mode("append").partitionBy("dt").save(path) 

我试着用saveAsTable到还使用兽人格式的蜂巢表,这似乎是快了大约20%至50%的速度,但这种方法有其自己的问题 - 似乎任务失败时,由于文件已存在,重试将始终失败。 这是我现在的储蓄数据帧

dt.write.format("orc").mode("append").partitionBy("dt").saveAsTable(tableName) 

是否有一个原因Save方法是如此之慢? 我做错了什么?

+0

6分钟写入50M文件并不那么慢。听起来像很多文件!每个人有多大?有多少执行者?如果它是每行一个文件,那就太多了。如果它们适用于您的存储系统,以及在典型查询中使用的节点/执行程序的数量,那么可能有50M是好的,但我对此表示怀疑。如果每个50M文件都是1G,那么〜47PB,所以我怀疑这一点。如果每个都是1MB,那么它就是47TB,我建议文件大小太小而无法有效地查询表格。总数据量是多少? – Davos

+0

它实际上是50兆文件。 – user1960555

+1

像,它只是一个50MB文件?如果它只是一个小文件,那么没有太多的点分区。有可能您的dt字段太多,最终会为每行创建分区。例如。如果是像“2017-01-01 14:52:22”那样的时间戳/日期时间,那么每隔一秒钟就会发生分区,然后为每个分区写入一个orc文件。 50MB可能是一个小文件,但它可能是很多具有不同时间戳的行。例如如果每一行是〜8K,那么~6400行,这是很多文件I/O。 – Davos

回答

1

问题是由于partitionBy方法。 PartitionBy读取指定列的值,然后为分区列的每个值分隔数据。 尽量保存它没有分区,会有显着的性能差异。

+0

我需要对数据进行分区,所以这不是一个选项。 – user1960555

+0

我认为这是一个有效的观点。什么是dt?这是一个合适的分区列吗?如果基数非常高,则可能不合适。例如,如果您对数据框的每一行使用的值不同,那么这会导致分区太多。所有文件I/O的开销都不值得。 – Davos

1

查看我之前关于基数和分区的评论。

如果你真的想对它进行分区,它只是一个50MB的文件,然后使用类似

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

再分配将创建4个大致相抵分区,而不是你在做在一个分区是什么dt列,最终可能会写很多orc文件。

4个分区的选择有点任意。你不会从分割这样的小文件中获得很多性能/并行化的好处。阅读更多文件的开销不值得。