Spark dynamic DAG намного медленнее и отличается от жестко закодированного DAG
У меня есть операция в спарк, которая должна быть выполнена для нескольких столбцов в кадре данных. Как правило, есть 2 возможности указать такие операции
жёсткоhandleBias("bar", df)
.join(handleBias("baz", df), df.columns)
.drop(columnsToDrop: _*).show
динамически генерировать их из списка именvar isFirst = true
var res = df
for (col <- columnsToDrop ++ columnsToCode) {
if (isFirst) {
res = handleBias(col, res)
isFirst = false
} else {
res = handleBias(col, res)
}
}
res.drop(columnsToDrop: _*).show
Проблема состоит в том, что динамически генерируемая группа доступности баз данных отличается, и время выполнения динамического решения увеличивается гораздо больше, когда используется больше столбцов, чем для жестко закодированных операций.
Мне любопытно каксочетать элегантность динамичной конструкции с быстрым временем выполнения.
Вот сравнение для групп DAG примера кода
Для около 80 столбцов это приводит к довольно хорошему графику для жестко закодированного вариантаИ очень большой, возможно, менее распараллеливаемый и значительно более медленный DAG для динамически сконструированного запроса.
Текущая версия spark (2.0.2) использовалась сDataFrames
и искра-sql
Код для завершения минимального примера:
def handleBias(col: String, df: DataFrame, target: String = "FOO"): DataFrame = {
val pre1_1 = df
.filter(df(target) === 1)
.groupBy(col, target)
.agg((count("*") / df.filter(df(target) === 1).count).alias("pre_" + col))
.drop(target)
val pre2_1 = df
.groupBy(col)
.agg(mean(target).alias("pre2_" + col))
df
.join(pre1_1, Seq(col), "left")
.join(pre2_1, Seq(col), "left")
.na.fill(0)
}
редактироватьВыполнение вашей задачи сfoldleft
генерирует линейный DAGи жесткое кодирование функции для всех столбцов приводит к
И то, и другое намного лучше, чем мои оригинальные DAG, но все же вариант в жестком коде выглядит лучше для меня. Конкатенация строк в SQL-выражении в spark может позволить мне динамически генерировать жестко запрограммированный граф выполнения, но это выглядит довольно уродливо. Видите ли вы какой-либо другой вариант?