AWS Glue上的Spark SQL:pyspark.sql.utils.AnalysisException

时间:2019-04-17 18:32:44

标签: apache-spark pyspark pyspark-sql aws-glue

我在AWS Glue脚本中使用Spark SQL来转换S3中的某些数据。 这是脚本逻辑

数据格式CSV

编程语言:Python

1)使用Glue的Catalog从S3提取数据到Glue的DynamicDataFrame

2)使用toDF()从Glue的数据框中提取Spark数据框

3)制作Spark数据框Spark SQL表

createOrReplaceTempView() 

4)使用SQL查询进行转换(这是我遇到问题的地方)

5)将最终数据帧转换为胶水动态数据帧

6)使用以下命令将最终数据帧存储到S3中 glueContext.write_dynamic_frame.from_options()

问题

当我在WHERE等SQL中使用比较时> 要么 (case when <some_columns> > <some int> then 1 else 0 end) as <some_newcol>

我遇到以下错误

pyspark.sql.utils.AnalysisException: u"cannot resolve '(sales.`cxvalue` >
100000)' due to data type mismatch: differing types in '(sales.`cxvalue` >
100000)' (struct<int:int,string:string> and int).; line 1 pos 35;\n'Project
['demand_amt]\n+- 'Filter (cxvalue#4 > 100000)\n +- SubqueryAlias sales\n +-
LogicalRDD [sales_id#0, customer_name#1, customer_loc#2, demand_amt#3L,
cxvalue#4]\n"
pyspark.sql.utils.AnalysisException: u"cannot resolve '(sales.`cxvalue` =
100000)' due to data type mismatch: differing types in '(sales.`cxvalue` =
100000)' (struct<int:int,string:string> and int).; line 1 pos 33;\n'Project
[customer_name#1, CASE WHEN (cxvalue#4 = 100000) THEN demand_amt#3 ELSE 0 END AS
small#12, CASE WHEN cxvalue#4 IN (200000,300000,400000) THEN demand_amt#3 ELSE 0
END AS medium#13]\n+- SubqueryAlias sales\n +- LogicalRDD [sales_id#0,
customer_name#1, customer_loc#2, demand_amt#3, cxvalue#4]\n"

这告诉我正在考虑将colums作为数字和字符串,这是特定于Spark而非AWS的。和() GROUP BY仅能很好地进行比较

我尝试了以下步骤

1)尝试使用Spark方法更改列类型-失败

df=df.withColumn(<column> df[<columns>].cast(DoubleType())) # df is Spark Data
111

胶水不允许更改spark数据框列类型的数据类型

2)如https://github.com/aws-samples/aws-gluesamples/中所述,使用了Glue的resoveChoice方法 blob / master / examples / resolve_choice.md。 resolveChoice方法有效-但sql失败,出现相同错误

3)在SQL查询中使用cast(<columns> as <data_type>) –失败

4)在我的Google Cloud上启动Spark集群(仅确保与AWS无关)。仅使用具有上述相同逻辑的Spark –失败,并出现相同的错误

5)在相同的Spark集群和相同的数据集上,使用相同的逻辑,但使用StructTypeStructField实施了强制模​​式 在创建新的Spark数据框时-已通过

这是示例数据

+--------+-------------+------------+----------+-------+
|sales_id|customer_name|customer_loc|demand_amt|cxvalue|
+--------+-------------+------------+----------+-------+
|       1|          ABC|   Denver CO|      1200| 300000|
|       2|          BCD|   Boston MA|       212| 120000|
|       3|          CDE|  Phoenix AZ|       332| 100000|
|       4|          BCD|   Boston MA|       211| 120000|
|       5|          DEF| Portland OR|      2121|1000000|
|       6|          CDE|  Phoenix AZ|        32| 100000|
|       7|          ABC|   Denver CO|      3227| 300000|
|       8|          DEF| Portland OR|      2121|1000000|
|       9|          BCD|   Boston MA|        21| 120000|
|      10|          ABC|   Denver CO|      1200|300000 |
+--------+-------------+------------+----------+-------+

这些是示例代码和查询失败的地方

sdf_sales.createOrReplaceTempView("sales")

tbl1="sales"

sql2="""select customer_name, (case when cxvalue  < 100000 then 1 else 0)  as small,   
(case when cxvalue  in (200000, 300000, 400000 ) then demand_amt else 0 end) as medium  
from {0}   
""".format(tbl1)

sql4="select demand_amt from {0} where cxvalue>100000".format(tbl1)

但是,这些查询与成功的Glue Job一起很好地工作

sql3="""select customer_name, sum(demand_amt) as total_spent from {0} GROUP BY  customer_name""".format(tbl1)

挑战: 希望以某种方式允许我更改Spark Dataframe模式。任何建议将不胜感激。

1 个答案:

答案 0 :(得分:0)

AWS Glue resolveChoice解决了该问题。 编程逻辑错误:将Spark Frame视为可变的