Apache spark 为什么流式查询会以“失败”而失败;InvalidSchemaException:组类型不能为空(…)空组:spark_schema“;在写拼花地板的时候?

Apache spark 为什么流式查询会以“失败”而失败;InvalidSchemaException:组类型不能为空(…)空组:spark_schema“;在写拼花地板的时候?,apache-spark,parquet,spark-structured-streaming,Apache Spark,Parquet,Spark Structured Streaming,我使用Spark 2.2.1和镶木地板1.8.1 我想从Kafka读取JSON数据并进行一些转换,然后将数据写入拼花地板文件,然后由Apache Hive加载。但我在将Stream写入拼花地板时遇到了以下错误 Caused by: org.apache.parquet.schema.InvalidSchemaException: A group type can not be empty. Parquet does not support empty group without leaves.

我使用Spark 2.2.1和镶木地板1.8.1

我想从Kafka读取JSON数据并进行一些转换,然后将数据写入拼花地板文件,然后由Apache Hive加载。但我在将Stream写入拼花地板时遇到了以下错误

Caused by: org.apache.parquet.schema.InvalidSchemaException: A group type can not be empty. Parquet does not support empty group without leaves. Empty group: spark_schema
    at org.apache.parquet.schema.GroupType.<init>(GroupType.java:92)
    at org.apache.parquet.schema.GroupType.<init>(GroupType.java:48)
    at org.apache.parquet.schema.MessageType.<init>(MessageType.java:50)
    at org.apache.parquet.schema.Types$MessageTypeBuilder.named(Types.java:1256)
    at org.apache.spark.sql.execution.datasources.parquet.ParquetSchemaConverter$.<init>(ParquetSchemaConverter.scala:563)
    at org.apache.spark.sql.execution.datasources.parquet.ParquetSchemaConverter$.<clinit>(ParquetSchemaConverter.scala)
    ... 22 more
程序可以打印模式并在数据框中显示一些数据

root
 |-- bot: boolean (nullable = true)
 |-- title: string (nullable = true)
 |-- user: string (nullable = true)
 |-- wiki: string (nullable = true)

-------------------------------------------
Batch: 0
-------------------------------------------
+-----+-----------------------------+----------+-----------+
|bot  |title                        |user      |wiki       |
+-----+-----------------------------+----------+-----------+
|false|Jak Roberto                  |WikiPedant|enwiki     |
|false|File:Oostkamp01.jpg          |Herpoel   |commonswiki|
|false|Category:CC-BY-SA-4.0        |Herpoel   |commonswiki|
|false|Category:Self-published work |Herpoel   |commonswiki|
|false|Category:Geography of Belgium|Herpoel   |commonswiki|
|false|Category:CC-BY-SA-4.0        |Herpoel   |commonswiki|
|false|Category:Self-published work |Herpoel   |commonswiki|
|false|Category:Geography of Belgium|Herpoel   |commonswiki|
|false|Category:CC-BY-SA-4.0        |Herpoel   |commonswiki|
|false|Category:Self-published work |Herpoel   |commonswiki|
|false|Category:Geography of Belgium|Herpoel   |commonswiki|
|false|Category:CC-BY-SA-4.0        |Herpoel   |commonswiki|
|false|Category:Self-published work |Herpoel   |commonswiki|
|false|Category:Geography of Belgium|Herpoel   |commonswiki|
|false|Category:CC-BY-SA-4.0        |Herpoel   |commonswiki|
|false|Category:Self-published work |Herpoel   |commonswiki|
|false|Category:Geography of Belgium|Herpoel   |commonswiki|
|true |Category:CC-BY-SA-4.0        |Herpoel   |commonswiki|
|true |Category:Self-published work |Herpoel   |commonswiki|
|true |Category:Geography of Belgium|Herpoel   |commonswiki|
+-----+-----------------------------+----------+-----------+
only showing top 20 rows

TL;DR升级到Spark 2.2.0(甚至更好地升级到2.2.1)

我认为这与提到错误消息和Spark有关

在parquet mr 1.8.1中,不再允许构造空的GroupType(因此也不允许构造MessageType)(参见parquet-278)。这种变化在大多数情况下是有意义的,因为拼花地板不支持空组。但是,有一种情况下空MessageType是有效的,即在计算拼花文件中的行时,将空MessageType作为ReadContext的requestedSchema构造函数参数传递。它工作的原因是,Parquet可以从块元数据中检索行数,而无需具体化任何列

随后在问题报告中:

我们可以看到sparksql没有将请求的列传递给底层的Parquet读取器

该问题报告与以下内容相关:

这将删除在PARQUET-278中添加的拒绝模式组的复选框 没有字段的。允许并使用从文件中选择0列 通过配置单元和SparkSQL实现查询,如select count(1)

拉取请求确实删除了检查(您在流数据集/Spark结构化流中一直面临的检查)

有了这些,我们了解到Spark中拼花地板的版本可能与1.8版本的分支有所不同

这导致了在中的讨论,该讨论最终以另一个被接受为将拼花地板版本升级到1.8.2的一部分而结束。这就是我们想要消除错误信息的拼花地板版本


由于Spark从Spark 2.2.0开始使用镶木地板1.8.2,我的建议是升级到Spark 2.2.0(甚至更好地升级到2.2.1)。

建议将镶木地板版本从1.8.1升级到1.8.2后,问题得到解决,谢谢Jacek!顺便说一下,1。如何控制每个拼花地板文件的大小?有这么多小文件。2.如何添加分区目录?我使用了partitionBy(“用户”),但似乎没有效果。我很困惑…在“将拼花地板版本从1.8.1升级到1.8.2”后,您是如何做到的?你说你使用Spark 2.2.1和镶木地板1.8.1,但我认为Spark 2.2.0使用镶木地板1.8.2,所以…请详细说明。谢谢
throw new InvalidSchemaException("A group type can not be empty. Parquet does not support empty group without leaves. Empty group: " + name);