无法增加 BufferHolder;超出大小限制

问题

Apache Spark 作业失败并出现 IllegalArgumentException: Cannot grow BufferHolder 错误。

java.lang.IllegalArgumentException: Cannot grow BufferHolder by size XXXXXXXXX because the size after growing exceeds size limitation 2147483632

原因

BufferHolder 的最大大小为 2147483632 字节(约 2 GB)。

如果列值超过此大小,Spark 将返回异常。

使用 collect_list 之类的聚合时可能会发生这种情况。

此示例代码在超过 BufferHolder 最大大小的列值中生成重复项。 因此,当在笔记本中运行时,它将返回 IllegalArgumentException: Cannot grow BufferHolder 错误。

import org.apache.spark.sql.functions._
spark.range(10000000).withColumn("id1",lit("jkdhdbjasdshdjkqgdkdkasldksashjckabacbaskcbakshckjasbc$%^^&&&&&*jxcfdkwbfkjwdqndlkjqslkndskbndkjqbdjkbqwjkdbxnsa xckqjwbdxsabvnxbaskxqbhwdhqjskdjxbqsjdhqkjsdbkqsjdkjqdhkjqsabcxns ckqjdkqsbcxnsab ckjqwbdjckqscx ns csjhdjkqsdhjkqshdjsdhqksjdhxqkjshjkshdjkqsdhkjqsdhjqskxb kqscbxkjqsc")).groupBy("id1").
agg(collect_list("id1").alias("days")).
show()

解决方案

必须确保列值不超过 2147483632 个字节。 这可能需要调整在笔记本中处理数据的方式。

查看我们的示例代码,使用 collect_set 而不是 collect_list,解决该问题并允许示例运行至完成。 这个更改之所以有效,是因为示例数据集包含大量重复项。

import org.apache.spark.sql.functions._
spark.range(10000000).withColumn("id1",lit("jkdhdbjasdshdjkqgdkdkasldksashjckabacbaskcbakshckjasbc$%^^&&&&&*jxcfdkwbfkjwdqndlkjqslkndskbndkjqbdjkbqwjkdbxnsa xckqjwbdxsabvnxbaskxqbhwdhqjskdjxbqsjdhqkjsdbkqsjdkjqdhkjqsabcxns ckqjdkqsbcxnsab ckjqwbdjckqscx ns csjhdjkqsdhjkqshdjsdhqksjdhxqkjshjkshdjkqsdhkjqsdhjqskxb kqscbxkjqsc")).groupBy("id1").
agg(collect_set("id1").alias("days")).
show()

如果使用 collect_set 不能使列的大小保持在 BufferHolder 限制(2147483632 字节)以下,则仍会出现 IllegalArgumentException: Cannot grow BufferHolder 错误。 在这种情况下,必须将列表拆分为多个数据帧,并将其作为单独的文件写出。