Apache Spark для аналитика: когда Pandas не хватает
Что такое Apache Spark
Apache Spark — это фреймворк для распределённой обработки больших данных. Если Pandas работает на одной машине и держит все данные в оперативной памяти, то Spark распределяет вычисления по кластеру из десятков или сотен серверов.
Для аналитика Spark — это инструмент, который появляется в жизни, когда данных становится слишком много. Пока таблица помещается в 16 ГБ RAM ноутбука — Pandas хватает. Когда таблица весит 500 ГБ — нужен Spark.
В крупных российских компаниях (Яндекс, Тинькофф, Сбер, VK, Озон) Spark — часть стандартного стека аналитика. На собеседованиях спрашивают не глубокое знание внутренностей, а умение писать запросы на PySpark или Spark SQL и понимание того, когда Spark необходим.
Когда Pandas не хватает
Pandas загружает весь датасет в RAM. Это значит:
- Лимит по памяти. Таблица в 10 ГБ займёт ~30 ГБ RAM (Pandas создаёт копии при операциях). На ноутбуке с 16 ГБ — не влезет.
- Одно ядро. Pandas по умолчанию использует одно ядро процессора. groupby на 100 млн строк — это минуты ожидания.
- Нет отказоустойчивости. Если процесс упал на середине — начинаете заново.
Spark решает все три проблемы: данные распределены по узлам, вычисления параллельны, при сбое узла задача переназначается.
Архитектура Spark: driver и executors
Spark работает по модели master-worker:
- Driver — главный процесс. Принимает ваш код, строит план выполнения, раздаёт задачи executors.
- Executors — рабочие процессы на узлах кластера. Выполняют вычисления и хранят данные в памяти.
- Cluster Manager — управляет ресурсами (YARN, Mesos, Kubernetes или standalone).
Когда вы пишете df.groupBy("city").count(), Spark не выполняет это сразу. Он строит DAG (Directed Acyclic Graph) — план выполнения, оптимизирует его и только потом запускает. Это называется lazy evaluation: трансформации накапливаются, а выполняются только при вызове действия (action) — .show(), .collect(), .write.
Основы PySpark
PySpark — Python API для Spark. Синтаксис напоминает Pandas, но с важными отличиями.
Создание сессии и чтение данных
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.appName("analytics") \
.getOrCreate()
# Чтение CSV
df = spark.read.csv("s3://bucket/orders.csv", header=True, inferSchema=True)
# Чтение Parquet (основной формат в Spark)
df = spark.read.parquet("s3://bucket/orders/")Базовые операции
from pyspark.sql import functions as F
# Фильтрация
active_users = df.filter(F.col("status") == "active")
# Группировка
revenue_by_city = (df
.groupBy("city")
.agg(
F.sum("revenue").alias("total_revenue"),
F.countDistinct("user_id").alias("users")
)
.orderBy(F.desc("total_revenue"))
)
# Оконная функция — ранг внутри группы
from pyspark.sql.window import Window
window = Window.partitionBy("category").orderBy(F.desc("revenue"))
df_ranked = df.withColumn("rank", F.row_number().over(window))
top3 = df_ranked.filter(F.col("rank") <= 3)JOIN
orders = spark.read.parquet("orders/")
users = spark.read.parquet("users/")
# LEFT JOIN
result = orders.join(users, orders.user_id == users.id, "left")Spark SQL
Если вы хорошо знаете SQL, Spark SQL — самый быстрый способ начать работать со Spark. Вы регистрируете DataFrame как временную таблицу и пишете обычный SQL.
df.createOrReplaceTempView("orders")
result = spark.sql("""
SELECT
city,
COUNT(DISTINCT user_id) AS users,
SUM(revenue) AS total_revenue,
AVG(revenue) AS avg_order
FROM orders
WHERE status = 'paid'
GROUP BY city
HAVING COUNT(DISTINCT user_id) >= 100
ORDER BY total_revenue DESC
""")
result.show(10)Spark SQL поддерживает оконные функции, CTE, подзапросы — всё, к чему вы привыкли. Под капотом Spark SQL и DataFrame API используют один и тот же оптимизатор (Catalyst), поэтому производительность одинаковая.
Spark vs Pandas: сравнение
| Критерий | Pandas | PySpark |
|---|---|---|
| Размер данных | До ~10 ГБ (зависит от RAM) | Терабайты и петабайты |
| Выполнение | Eager (сразу) | Lazy (по требованию) |
| Параллелизм | Одно ядро | Кластер из N узлов |
| Синтаксис | df['col'], groupby() |
F.col('col'), groupBy() |
| Скорость на малых данных | Быстрее (нет оверхеда) | Медленнее (запуск кластера) |
| Отладка | Простая (print, IDE) | Сложнее (распределённая среда) |
| Формат данных | CSV, Excel, JSON | Parquet, ORC, Delta Lake, CSV |
Правило большого пальца: если данные помещаются в память одной машины — Pandas. Если нет — Spark. Если данные в «серой зоне» (5-20 ГБ) — можно попробовать Pandas с оптимизацией (фильтрация при чтении, уменьшение типов данных) или Polars.
Когда аналитик встречает Spark
Типичные ситуации:
- ETL-пайплайны. Данные из источников (логи, события, транзакции) агрегируются Spark-джобами. Аналитик пишет или дебажит эти джобы.
- Ad-hoc анализ больших данных. Нужно посчитать метрику по всем пользователям за год — 500 млн строк. В Jupyter с PySpark или через Spark SQL в Zeppelin/Databricks.
- Подготовка фичей для ML. Фичи считаются на кластере, потому что на одной машине это заняло бы сутки.
- Работа с data lake. Данные лежат в S3/HDFS в формате Parquet — Spark читает их нативно.
Вопросы с собеседований
Чем Spark отличается от Pandas?
Spark — распределённый фреймворк, обрабатывает данные на кластере. Pandas — библиотека для одной машины. Spark использует lazy evaluation (DAG), Pandas выполняет операции сразу. Spark масштабируется горизонтально, Pandas ограничен RAM одного сервера.
Что такое lazy evaluation в Spark?
Трансформации (filter, groupBy, join) не выполняются сразу — Spark строит граф вычислений (DAG). Выполнение запускается только при вызове действия (action): show(), collect(), write(). Это позволяет оптимизатору Catalyst перестроить план выполнения для максимальной эффективности.
Что такое partition в Spark и зачем нужен repartition?
Partition — это часть данных, которая обрабатывается одним executor'ом. Если данные неравномерно распределены (data skew), один executor будет перегружен, остальные простаивают. repartition() перераспределяет данные, coalesce() уменьшает количество партиций без полного перемешивания.
Когда бы вы выбрали Spark SQL вместо PySpark DataFrame API?
Если задача хорошо ложится на SQL — Spark SQL проще и читабельнее. Для сложной логики с условиями, UDF и многоэтапными трансформациями — DataFrame API гибче. Производительность одинаковая — оба используют Catalyst optimizer.
FAQ
Нужно ли аналитику знать Spark?
Зависит от компании. В крупных компаниях с big data (Яндекс, Сбер, VK, Тинькофф) — да, это базовое требование. В стартапах с небольшим объёмом данных — Pandas хватает. Если целитесь в крупные компании, базовые PySpark и Spark SQL стоит освоить.
Можно ли использовать Spark локально для обучения?
Да. PySpark устанавливается через pip install pyspark и работает на одной машине в режиме local[*]. Это не даёт масштабирования, но позволяет отработать синтаксис и логику. Для реальных задач используют Databricks Community Edition (бесплатный) или Google Colab с PySpark.
Чем Spark отличается от Hadoop MapReduce?
Spark — эволюция MapReduce. Главное отличие: Spark хранит промежуточные данные в памяти, а MapReduce записывает на диск после каждого шага. Поэтому Spark в 10-100 раз быстрее на итеративных задачах (ML, многоэтапные агрегации). MapReduce сегодня почти не используется напрямую.
Потренируйте вопросы по SQL и Python на реальных задачах — откройте тренажёр. 1500+ вопросов, которые спрашивают на собеседованиях аналитика. Бесплатно.