首页 > 解决方案 > 使用 AWS Glue 表分区的 EMR 笔记本中的 Spark SQL 错误

问题描述

在部署之前,我在 EMR 笔记本中测试了一些 pyspark 代码,并在 Spark SQL 中不断遇到这个奇怪的错误。我的所有表和元数据都与 AWS Glue 目录集成,以便我可以通过 spark 读取和写入它们。

代码的第一部分从 S3/Glue 读取一些数据,进行一些转换,然后将生成的数据帧写入 S3/Glue,如下所示:

df.repartition('datekey','coeff')\
    .write\
    .format('parquet')\
    .partitionBy('datekey','coeff')\
    .mode('overwrite')\
    .option("path", S3_PATH)\
    .saveAsTable('hive_tables.my_table')

然后我尝试使用 Spark SQL 访问这个表,但是当我运行一些简单的东西时 spark.sql('select * from hive_tables.my_table where datekey=20210506').show(),它会抛出这个:

An error was encountered:
"org.apache.hadoop.hive.metastore.api.InvalidObjectException: Unknown type : 'double' (Service: AWSGlue; Status Code: 400; Error Code: InvalidInputException; Request ID: 43ff3707-a44f-41be-b14a-7b9906d8d8f9; Proxy: null);"
Traceback (most recent call last):
  File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/sql/readwriter.py", line 778, in saveAsTable
    self._jwrite.saveAsTable(name)
  File "/usr/lib/spark/python/lib/py4j-0.10.7-src.zip/py4j/java_gateway.py", line 1257, in __call__
    answer, self.gateway_client, self.target_id, self.name)
  File "/usr/lib/spark/python/lib/pyspark.zip/pyspark/sql/utils.py", line 69, in deco
    raise AnalysisException(s.split(': ', 1)[1], stackTrace)
pyspark.sql.utils.AnalysisException: "org.apache.hadoop.hive.metastore.api.InvalidObjectException: Unknown type : 'double' (Service: AWSGlue; Status Code: 400; Error Code: InvalidInputException; Request ID: 43ff3707-a44f-41be-b14a-7b9906d8d8f9; Proxy: null);"

我了解到只有在指定 datekey 分区时才会发生这种情况。例如,以下两个命令都可以正常工作: spark.sql('select * from hive_tables.my_table where coeff=0.5').show()spark.sql('select * from hive_tables.my_table').show()

我已经通过 Spark SQL 验证了分区存在并且其中有数据。该datekey查询也可以通过 AWS Athena 正常运行——只是 Spark SQL 不行。

Glue 也肯定有两个分区列被识别:

datekey: int
coeff: double

这里有什么想法吗?我已经尝试了我能想到的一切,但它没有任何意义。

标签: amazon-web-servicespysparkapache-spark-sqlamazon-emraws-glue

解决方案


我仍然想要一个直接的解决方案,但目前这种解决方法就足够了:

我首先直接从 S3 路径读取表格

temp_df = spark.read.parquet(S3_PATH)

这样它就不会使用 Glue 目录作为元数据。然后我为会话创建一个临时表:

temp_df.createGlobalTempView('my_table')

这允许我使用带有global_temp数据库的 Spark SQL 来查询它:

spark.sql('select * from global_temp.my_table where datekey=20210506').show()

这有效


推荐阅读