我使用Spark 2.2.1和Scala 2.11使用DataBricks。我正在尝试运行如下所示的SQL查询。
select stddev(col1), stddev(col2), ..., stddev(col1300)
from mydb.mytable
然后我按如下方式执行代码。
myRdd = sqlContext.sql(sql)
但是,我看到抛出以下异常。
Job aborted due to stage failure: Task 24 in stage 16.0 failed 4 times, most recent failure: Lost task 24.3 in stage 16.0 (TID 1946, 10.184.163.105, executor 3): org.codehaus.janino.JaninoRuntimeException: failed to compile: org.codehaus.janino.JaninoRuntimeException: Constant pool for class org.apache.spark.sql.catalyst.expressions.GeneratedClass$SpecificMutableProjection has grown past JVM limit of 0xFFFF /* 001 */ public java.lang.Object generate(Object[] references) { /* 002 */ return new SpecificMutableProjection(references); /* 003 */ } /* 004 */ /* 005 */ class SpecificMutableProjection extends org.apache.spark.sql.catalyst.expressions.codegen.BaseMutableProjection { /* 006 */ /* 007 */ private Object[] references; /* 008 */ private InternalRow mutableRow; /* 009 */ private boolean evalExprIsNull; /* 010 */ private boolean evalExprValue; /* 011 */ private boolean evalExpr1IsNull; /* 012 */ private boolean evalExpr1Value; /* 013 */ private boolean evalExpr2IsNull; /* 014 */ private boolean evalExpr2Value; /* 015 */ private boolean evalExpr3IsNull; /* 016 */ private boolean evalExpr3Value; /* 017 */ private boolean evalExpr4IsNull; /* 018 */ private boolean evalExpr4Value; /* 019 */ private boolean evalExpr5IsNull; /* 020 */ private boolean evalExpr5Value; /* 021 */ private boolean evalExpr6IsNull;
堆栈跟踪一直在继续,甚至Databricks笔记本也因为冗长而崩溃。有人见过这个吗?
另外,我有以下2个SQL语句来获取我执行的平均值和中位数而没有任何问题。
select avg(col1), ..., avg(col1300) from mydb.mytable
select percentile_approx(col1, 0.5), ..., percentile_approx(col1300, 0.5) from mydb.mytable
问题似乎是stddev
,但例外没有帮助。关于发生了什么的任何想法?是否有另一种方法可以轻松计算标准偏差,从而不会导致这个问题?
事实证明,post描述了同样的问题,因为64KB大小的类的限制,Spark无法处理宽模式或大量列。但是,如果是这种情况,那么为什么avg
和percentile_approx
有效?
答案 0 :(得分:1)
一些选择:
尝试禁用整个阶段代码生成:
spark.conf.set("spark.sql.codegen.wholeStage", false)
如果以上内容无法切换到RDD(this answer从zeo323采用):
import org.apache.spark.mllib.linalg._
import org.apache.spark.mllib.stat.MultivariateOnlineSummarizer
val columns: Seq[String] = ???
df
.select(columns map (col(_).cast("double")): _*)
.rdd
.map(row => Vectors.dense(columns.map(row.getAs[Double](_)).toArray))
.aggregate(new MultivariateOnlineSummarizer)(
(agg, v) => agg.add(v),
(agg1, agg2) => agg1.merge(agg2))
使用VectorAssembler
将列组合到单个向量中并使用Aggregator
,类似于使用here的列,调整finish
方法(您可能需要一些额外调整以将ml.linalg.Vectors
转换为mllib.linalg.Vectors
)。
但是,如果是这样的话,为什么avg和percentile_approx有效呢?
Spark从字面上为这些阶段生成Java代码。由于逻辑不相同,因此输出大小会有所不同。