使用空数据集的Spark SQL连接会导致更大的输出文件大小

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用空数据集的Spark SQL连接会导致更大的输出文件大小相关的知识,希望对你有一定的参考价值。

我遇到了一个问题,其中显然在Spark SQL中使用空表执行完全外连接会导致文件大小比仅仅从其他数据集中选择列而不进行连接。

基本上,我有两个数据集,其中一个非常大,另一个是空的。我经历了从大型数据集中选择几乎所有列,并将其全外部连接到空数据集。然后,我将结果数据集写入snappy-compressed镶木地板(我也尝试使用snappy压缩的orc)。或者,我只是从大数据集中选择相同的列,然后将结果数据集保存为如上所述的snappy压缩拼花(或orc)。文件大小完全不同,因为来自empty-dataset-join的文件几乎是简单选择文件的五倍。

我已经在许多不同的数据集上尝试了这一点,并得到了相同的结果。在查看数据时:

  • 输出行数相同(通过读取输出数据集并进行计数,使用spark-shell进行验证)
  • 架构是相同的(使用spark-shell,镶木地板工具和orc-tools验证)
  • 现场检查数据看起来是一样的,我在任何一种输出中都看不到任何疯狂的数据
  • 我明确保存了所有带有相同的,snappy,压缩和输出文件的文件被Spark赋予'.snappy.parquet'扩展名

我理解使用空表进行连接实际上是没有意义的(我这样做是作为一些通用代码的一部分,它总是执行完全外连接,有时会遇到空数据集)。而且,我已经更新了我的代码,所以它不再这样做,所以问题得到解决。

不过,我想了解为什么/如何发生这种情况。所以我的问题是 - 为什么使用空数据集进行Spark SQL连接会导致更大的文件大小?和/或关于如何弄清楚生成的镶木地板文件如此之大的任何想法也会有所帮助。

答案

在遇到其他几种情况之后,处理数据的方式看似微小的差异导致文件大小的巨大差异(对于看似完全相同的数据),我终于弄明白了。

这里的关键是理解镶木地板(或orc)如何使用可能复杂的格式(如字典编码,游程编码等)对数据进行编码。这些格式利用数据冗余来缩小文件大小,即,如果您的数据包含大量类似的值,文件大小将小于许多不同的值。

在连接空数据集的情况下,重要的一点是当spark执行连接时,它会在连接列上进行分区。因此,即使使用空数据集,进行连接也可能会更改数据的分区方式。

在我的例子中,使用空数据集连接将分区从多个类似记录在每个分区中组合在一起的分区更改为在每个分区中分组了许多不同记录的分区。然后,当写出这些分区时,在每个文件中放入许多相似或不相似的记录。当分区具有相似的记录时,镶木地板的编码效率非常高,文件大小也很小;当分区多样化时,镶木地板的编码效率不高,文件大小也更大 - 即使整体数据完全相同。

如上所述,我们遇到了同样问题出现的其他几个实例 - 我们改变了处理的一个方面,并且会获得相同的输出数据,但文件大小可能会大四倍。有助于解决这个问题的一件事是使用parquet-tools来查看低级文件统计信息。

以上是关于使用空数据集的Spark SQL连接会导致更大的输出文件大小的主要内容,如果未能解决你的问题,请参考以下文章

大数据(spark sql 和 spark dataframes 连接)

Spark 2.2 空安全左外连接空指针异常

MapReduce模型中数据关联使用or语句导致计算效率低下

Apache Spark - 在java中返回空数据集的映射函数

小型图像数据集的数据增强技术?

Java Spark:使用未知连接列名称连接的数据集的 Spark 错误解决方法