Ответ
В Apache Spark операции делятся на два основных типа: трансформации (transformations) и действия (actions).
Трансформации — ленивые операции, которые создают новую RDD, DataFrame или Dataset из существующей. Они не выполняются немедленно, а лишь строят граф вычислений (DAG).
- Поэлементные преобразования:
map(),flatMap(),filter(). - Агрегации и соединения:
groupBy(),reduceByKey(),join(),union(). - Изменение партиционирования:
repartition(),coalesce().
Действия — операции, которые запускают вычисления, возвращают результат в драйвер-программу или сохраняют данные. Они заставляют выполниться все накопленные трансформации.
- Сбор данных:
count(),collect(),take(),first(). - Сохранение:
saveAsTextFile(),write().parquet(),write().csv(). - Агрегация:
reduce(),aggregate(),foreach().
Пример на Scala с RDD:
// Трансформации (ленивые)
val rdd = sc.parallelize(Seq(1, 2, 3, 4, 5))
val transformedRdd = rdd.filter(_ % 2 == 0).map(_ * 10) // Фильтр и умножение
// Действие (запускает вычисления)
val result = transformedRdd.collect() // Array(20, 40)
println(result.mkString(", "))
Ключевое отличие: Трансформации определяют что вычислять, а действия — когда начинать вычисления и что с результатом делать.
Ответ 18+ 🔞
Давай разберём эту тему, а то некоторые до сих пор путаются, как будто на дворе 2002-й год. В Apache Spark, ёпта, есть всего два типа операций, и это надо запомнить, как своё имя.
Первые — это трансформации (transformations). Это такие ленивые твари, которые нихуя не делают сразу. Они просто строят план, типа "эй, чувак, вот когда-нибудь потом мы возьмём эти данные и сделаем вот так". Создают они новый RDD, DataFrame или Dataset, но реальных вычислений пока ноль. Просто рисуют граф в воздухе, доверия ебать ноль к их исполнительности на этом этапе.
Что к ним относится? Ну, например:
- Поэлементные преобразования:
map(),flatMap(),filter()— каждый элемент по отдельности трогают. - Агрегации и соединения:
groupBy(),reduceByKey(),join()— тут уже данные начинают общаться между собой. - Изменение партиционирования:
repartition(),coalesce()— это когда ты решаешь, по сколько строк в каждой пачке таскать.
А вторые — это действия (actions). Вот это уже серьёзные пацаны. Это команда "пиздуй делать!". Они-то и запускают весь этот цирк, заставляя все накопленные ленивые трансформации наконец-то отработать. Результат либо возвращается к тебе в программу, либо пишется куда-то на диск.
Примеры действий:
- Сбор данных:
count(),collect(),take()— выгребают всё из кластера к драйверу. Сcollect()осторожно, а то можно такую овердохуища данных притащить, что драйвер накроется медным тазом. - Сохранение:
saveAsTextFile(),write().parquet()— тут всё понятно, сохраняем и идём пить чай. - Агрегация:
reduce(),aggregate()— сводят всё к какому-то одному значению.
Ключевое отличие, блядь, вот в чём: Трансформации — это как составить список покупок. Действия — это как пойти в магазин, отстоять очередь и всё это купить. Пока не скажешь "collect()" — никакого реального движения данных не будет, терпения ноль ебать у этой системы.
Смотри на примере, чтобы вообще ни у кого сомнений не осталось:
// Трансформации (ленивые, нихуя не происходит)
val rdd = sc.parallelize(Seq(1, 2, 3, 4, 5))
val transformedRdd = rdd.filter(_ % 2 == 0).map(_ * 10) // Пока только планы, блядь!
// Действие (ВЖУХ! и понеслась!)
val result = transformedRdd.collect() // Вот тут Spark просыпается и начинает работать
println(result.mkString(", "))
Вот и вся магия. Запомни: пока не вызвал действие — можешь строить хоть хуй в пальто из трансформаций, вычисляться ничего не будет. Как только вызвал — ёперный театр, поехали.