Spark Catalog API на собеседовании Data Engineer

Проверь себя · 1/3разбор после ответа
Что вернёт запрос SELECT DISTINCT city, country FROM users, если в таблице есть повторяющиеся пары city-country?

Зачем нужен catalog

Catalog в Spark — это реестр метаданных: он знает, какие есть базы, таблицы и представления, где физически лежат их данные и какая у них схема. Когда вы пишете spark.sql('SELECT * FROM orders'), Spark идёт именно в catalog, чтобы понять, что такое orders и откуда его читать. Без catalog была бы просто «папка с parquet-файлами», а с ним — полноценные таблицы с именами и схемой.

На собесе Data Engineer это спрашивают, чтобы проверить, понимаете ли вы разницу между временным и постоянным, между таблицей, за данные которой отвечает Spark, и таблицей, где он хранит только метаданные. Здесь легко проколоться на, казалось бы, мелочи — например, случайно удалить данные вместе с таблицей.

Catalog в Spark

Обращаться к реестру можно программно через spark.catalog:

spark.catalog.listDatabases()            # список баз
spark.catalog.listTables('my_db')        # таблицы в базе
spark.catalog.tableExists('my_db.my_table')  # существует ли таблица

Эти методы удобны, когда пайплайн должен проверить наличие таблицы перед записью или пройтись по списку объектов. Всё то же самое доступно и через SQL (SHOW TABLES, SHOW DATABASES).

Временные представления

Temp view — сессионное представление: именованная ссылка на DataFrame, видимая только внутри текущей SparkSession. В метастор оно не пишется, между приложениями не шарится.

df.createOrReplaceTempView('my_view')
spark.sql('SELECT * FROM my_view')

После spark.stop() представление исчезает — оно живёт ровно столько, сколько живёт сессия. Важный нюанс: temp view сам по себе не кэширует данные, это просто именованный логический план; при каждом запросе он вычисляется заново, если вы явно не сделали cache().

Global temp view видно во всех сессиях одного Spark-приложения — оно живёт в специальной базе global_temp. Но как только приложение завершится, представление тоже исчезнет:

df.createGlobalTempView('global_view')
spark.sql('SELECT * FROM global_temp.global_view')

Постоянные таблицы

Постоянная таблица сохраняется в catalog вместе с метаданными (через Hive Metastore, Iceberg и т.п.) и переживает перезапуск сессии:

df.write.saveAsTable('my_db.my_table')
spark.sql('SELECT * FROM my_db.my_table')

Catalog запоминает расположение данных и схему, поэтому таблица доступна и в следующей сессии, и другим движкам, читающим тот же метастор.

Здесь важна ключевая для собеса развилка — managed vs external:

  • Managed (внутренняя) таблица. Spark управляет и метаданными, и данными. Данные лежат в служебной директории склада (warehouse). DROP TABLE удалит и метаданные, и сами файлы.
  • External (внешняя) таблица. Создаётся с явным LOCATION. Spark управляет только метаданными, а данные — «чужие». DROP TABLE уберёт запись из catalog, но файлы останутся на месте.

Разница между ними — любимый вопрос интервьюера, потому что путаница здесь приводит к реальной потере данных в продакшене.

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Виды каталогов

Тип catalog задаётся через spark.sql.catalogImplementation и внешние коннекторы:

  • In-memory (по умолчанию, если не подключён Hive). Реестр живёт в памяти драйвера и теряется при остановке приложения. Годится для локальной разработки, не для продакшена.
  • Hive Metastore. Стандарт для big data: постоянный, общий для Spark, Trino и Hive. Долгие годы — дефолт в дата-платформах.
  • Iceberg REST catalog. Современный каталог для таблиц Apache Iceberg, работает по REST-протоколу.
  • AWS Glue. Управляемый Hive-совместимый каталог в экосистеме AWS.
  • Unity Catalog. Каталог lakehouse от Databricks с управлением доступом и происхождением данных.
  • Polaris. Iceberg-совместимый каталог, вышедший из Snowflake (Apache Polaris).

Переключение реализации — через конфиг, например spark.sql.catalogImplementation=hive.

Интеграция с Iceberg и Delta

Через catalog Spark работает с современными табличными форматами lakehouse.

Iceberg:

spark.sql("""
  CREATE TABLE my_db.events (
    id BIGINT, ts TIMESTAMP
  ) USING iceberg
  PARTITIONED BY (days(ts))
""")

Связка Spark + Iceberg — типичный современный lakehouse: ACID-транзакции, эволюция схемы, time travel поверх файлов в объектном хранилище.

Delta Lake:

df.write.format("delta").save("/path/to/table")
spark.sql("CREATE TABLE my_db.events USING delta LOCATION '/path/to/table'")

У Delta time travel и ACID тоже встроены — разница в основном в экосистеме и деталях реализации.

Частые ошибки

  • Удалить данные вместе с managed-таблицей. Сделать DROP TABLE на внутренней таблице, думая, что удаляете только метаданные, — и потерять файлы. Для «чужих» данных всегда создавайте external-таблицу с LOCATION.
  • Ждать, что temp view переживёт сессию. Временное представление исчезает вместе с сессией, а global temp view — вместе с приложением. В метастор они не попадают.
  • Считать, что temp view кэширует данные. Это только именованный логический план; без явного cache() он пересчитывается при каждом запросе.
  • Полагаться на in-memory catalog в продакшене. Дефолтный in-memory реестр теряется при остановке приложения — для постоянных таблиц нужен Hive Metastore, Glue, Unity или Iceberg REST.
  • Путать базу и catalog. В современном Spark может быть несколько каталогов (multi-catalog), и полное имя таблицы — это catalog.database.table, а не просто database.table.

Связанные темы

FAQ

Чем temp view отличается от постоянной таблицы?

Temp view — сессионная именованная ссылка на DataFrame; она не пишется в метастор и исчезает при завершении сессии. Постоянная таблица регистрируется в catalog вместе со схемой и расположением данных, переживает перезапуск сессии и доступна другим движкам, читающим тот же метастор.

В чём разница между managed и external таблицей?

Managed-таблицей Spark управляет полностью: DROP TABLE удаляет и метаданные, и файлы данных. External-таблица создаётся с явным LOCATION, и Spark отвечает только за метаданные — при DROP TABLE файлы остаются на месте. Для данных, которыми владеет не Spark, используют external, чтобы случайно их не удалить.

Что такое global temp view и как долго он живёт?

Это представление, видимое во всех сессиях одного Spark-приложения; оно хранится в служебной базе global_temp (обращаться нужно как global_temp.имя). Живёт до завершения приложения — при его остановке представление исчезает, в метастор оно не сохраняется.

Зачем нужен Hive Metastore, если есть in-memory catalog?

In-memory catalog живёт в памяти драйвера и теряется при остановке приложения — постоянные таблицы в нём не переживут перезапуск. Hive Metastore (или Glue, Unity, Iceberg REST) — это внешнее постоянное хранилище метаданных, общее для Spark, Trino и Hive, поэтому таблицы доступны разным движкам и не пропадают между запусками.

Это официальная информация?

Нет. Статья основана на документации Spark, Iceberg и Delta. Конкретный синтаксис и набор доступных каталогов зависят от версии Spark и вашей платформы — сверяйтесь с документацией окружения.


Тренируйте Data Engineering — откройте тренажёр с 1500+ вопросами для собесов.