У меня основной вопрос по работе со Spark DataFrame.

Рассмотрим следующий фрагмент псевдокода:

val df1 = // Lazy Read from csv and create dataframe
val df2 = // Filter df1 on some condition
val df3 = // Group by on df2 on certain columns
val df4 = // Join df3 with some other df

val subdf1 = // All records from df4 where id < 0
val subdf2 =  // All records from df4 where id > 0

* Then some more operations on subdf1 and subdf2 which won't trigger spark evaluation yet*

// Write out subdf1
// Write out subdf2

Предположим, я начинаю с основного фрейма данных df1 (который я лениво читаю из CSV), выполняю некоторые операции с этим фреймом данных (фильтрация, группировка, соединение), а затем наступает момент, когда я разделяю этот фрейм данных на основе условия ( например, для id> 0 и id <0). Затем я продолжаю работать с этими субфреймами данных (назовем их subdf1, subdf2) и в конечном итоге записываю оба субфрейма данных.

Обратите внимание, что функция write - единственная команда, которая запускает вычисление искры, а остальные функции (фильтр, группировка, соединение) приводят к ленивым вычислениям.

Теперь, когда я записываю subdf1, я понимаю, что срабатывает ленивая оценка, и все операторы оцениваются, начиная с чтения CSV для создания df1.

У меня вопрос возникает, когда мы начинаем выписывать subdf2. Понимает ли Spark расхождение в коде в df4 и сохраняет ли этот фрейм данных, когда была обнаружена команда для записи subdf1? Или он снова начнется с первой строки создания df1 и переоценит все промежуточные фреймы данных? Если да, то стоит ли cache фрейм данных df4 (при условии, что у меня достаточно памяти)?

Я использую Scala Spark, если это важно. Любая помощь будет оценена по достоинству.

0
Abhishek 12 Фев 2021 в 09:27

1 ответ

Лучший ответ

Нет, Spark не может сделать этого вывода из вашего кода. Все начнется сначала. Чтобы подтвердить это, вы можете использовать subdf1.explain() и subdf2.explain(), и вы должны увидеть, что оба фрейма данных имеют планы запросов, которые начинаются с самого начала, где был прочитан df1.

Итак, вы правы, что вам следует кэшировать df4, чтобы избежать повторения всех вычислений, начиная с df1, если у вас достаточно памяти. И, конечно же, не забудьте не настаивать, выполнив df4.unpersist() в конце, если вам больше не нужно df4 для дальнейших вычислений.

0
mck 12 Фев 2021 в 07:43