Spark Catalog API на собеседовании Data Engineer
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, но файлы останутся на месте.
Разница между ними — любимый вопрос интервьюера, потому что путаница здесь приводит к реальной потере данных в продакшене.
Виды каталогов
Тип 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.
Связанные темы
- Hive Metastore для DE
- Iceberg deep для DE
- Spark RDD vs DataFrame для DE
- Lakehouse Iceberg Delta для DE
- Подготовка к собесу Data Engineer
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+ вопросами для собесов.