Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 如何停止在条件语句中解析UDF列_Apache Spark_Pyspark_Apache Spark Sql - Fatal编程技术网

Apache spark 如何停止在条件语句中解析UDF列

Apache spark 如何停止在条件语句中解析UDF列,apache-spark,pyspark,apache-spark-sql,Apache Spark,Pyspark,Apache Spark Sql,我想执行一些条件分支以避免计算不必要的节点,但我注意到,如果condition语句中的source列是一个UDF,那么否则将被解析,不管: @pandas_udf("double", PandasUDFType.SCALAR) def udf_that_throws_exception(*cols): raise Exception('Error') @pandas_udf("int", PandasUDFType.SCALAR) def simple_mul_udf(*cols

我想执行一些条件分支以避免计算不必要的节点,但我注意到,如果condition语句中的source列是一个UDF,那么否则将被解析,不管:

 @pandas_udf("double", PandasUDFType.SCALAR)
 def udf_that_throws_exception(*cols):
   raise Exception('Error')

 @pandas_udf("int", PandasUDFType.SCALAR)
 def simple_mul_udf(*cols):
   result = cols[0]
   for c in cols[1:]:
     result *= c
   return result

 df = spark.range(0,5)

 df = df.withColumn('A', lit(1))
 df = df.withColumn('B', lit(2))

 df = df.withColumn('udf', simple_mul('A','B'))
 df = df.withColumn('sql', expr('A*B'))

 df = df.withColumn('res', when(df.sql < 100, lit(1)).otherwise(udf_that_throws(lit(0))))
  df = df.withColumn('cond', when(df.udf < 100, lit(1)).otherwise(lit(0)))
  df = df.withColumn('res', when(df.cond == lit(1), lit(1)).otherwise(udf_that_throws_exception(lit(0))))
@pandas\u udf(“double”,PandasUDFType.SCALAR)
抛出异常(*cols)的def udf_:
引发异常('错误')
@pandas_udf(“int”,PandasUDFType.SCALAR)
定义简单多个自定义项(*cols):
结果=cols[0]
对于cols[1:]中的c:
结果*=c
返回结果
df=火花范围(0,5)
df=df.带柱('A',发光(1))
df=带柱的df('B',发光(2))
df=df.withColumn('udf',simple_mul('A','B'))
df=df.withColumn('sql',expr('A*B'))
df=df.withColumn('res',当(df.sql<100,lit(1))。否则(udf_抛出(lit(0)))
上述代码按预期工作,本例中的语句始终为true,因此不会调用引发异常的我的UDF

但是,如果我将条件改为使用df.udf,则会突然调用否则的udf,即使条件结果没有更改,我也会得到异常

我想我可以通过从条件中删除UDF来混淆它,但是不管怎样,都会出现相同的结果:

 @pandas_udf("double", PandasUDFType.SCALAR)
 def udf_that_throws_exception(*cols):
   raise Exception('Error')

 @pandas_udf("int", PandasUDFType.SCALAR)
 def simple_mul_udf(*cols):
   result = cols[0]
   for c in cols[1:]:
     result *= c
   return result

 df = spark.range(0,5)

 df = df.withColumn('A', lit(1))
 df = df.withColumn('B', lit(2))

 df = df.withColumn('udf', simple_mul('A','B'))
 df = df.withColumn('sql', expr('A*B'))

 df = df.withColumn('res', when(df.sql < 100, lit(1)).otherwise(udf_that_throws(lit(0))))
  df = df.withColumn('cond', when(df.udf < 100, lit(1)).otherwise(lit(0)))
  df = df.withColumn('res', when(df.cond == lit(1), lit(1)).otherwise(udf_that_throws_exception(lit(0))))
df=df.withColumn('cond',当(df.udf<100,lit(1))。否则(lit(0)))
df=df.withColumn('res',when(df.cond==lit(1),lit(1))。否则(引发异常的udf(lit(0)))
我想这与Spark优化的方式有关,这很好,但我正在寻找任何不产生成本的方法来实现这一点。有什么想法吗

编辑 请按要求提供更多信息。我们正在编写一个可以接受任意模型的处理引擎,代码生成图形。在此过程中,我们会根据运行时的值状态做出决策。我们大量使用熊猫UDF。因此,想象一下这样一种情况:图形中有多条路径,并且根据运行时的某些条件,我们希望遵循其中一条路径,而不触及其他所有路径

我想将这个逻辑编码到图中,这样就不需要在代码中收集和分支


我提供的示例代码仅用于演示目的。我所面临的问题是,如果if语句中使用的列是一个UDF,或者,如果它似乎是从一个UDF派生出来的,那么即使它从未实际使用过,否则条件也总是被执行。如果If/ELSE是廉价的操作,例如文字,我不介意,但是如果列UDF(可能在两侧)导致一个大的聚合或其他实际上刚刚丢弃的长度过程,该怎么办?

在PySpark中,UDF是预先计算的,因此您得到的是次优的行为。您也可以从查询计划中看到它:

== Physical Plan ==
*(2) Project [id#753L, 1 AS A#755, 2 AS B#758, pythonUDF1#776 AS udf#763, CASE WHEN (pythonUDF1#776 < 100) THEN 1.0 ELSE pythonUDF2#777 END AS res#769]
+- ArrowEvalPython [simple_mul_udf(1, 2), simple_mul_udf(1, 2), udf_that_throws_exception(0)], [id#753L, pythonUDF0#775, pythonUDF1#776, pythonUDF2#777]
   +- *(1) Range (0, 5, step=1, splits=8)

你能解释清楚你的问题吗..你在使用df.udf时遇到了什么问题?请同时添加udf的逻辑