Отправьте статью сегодня! Журнал выйдет ..., печатный экземпляр отправим ...
Опубликовать статью

Молодой учёный

Архитектура метаданных, статистика и механизмы отброса данных в Apache Iceberg при использовании Apache Spark 3.5

Научный руководитель
Информационные технологии
18.05.2026
Поделиться
Аннотация
В статье рассматриваются особенности архитектуры хранения метаданных и статистики в Apache Iceberg при использовании Apache Spark 3.5. Проведён анализ взаимодействия физических и логических уровней хранения данных на основе форматов Parquet и Iceberg, а также исследованы механизмы многоуровневого отброса данных (Data Pruning), обеспечивающие снижение объёма операций ввода-вывода и повышение производительности аналитических запросов. Особое внимание уделено влиянию статистики на работу Cost-Based Optimizer и Adaptive Query Execution в Spark, проблемам деградации производительности при фрагментации метаданных и накоплении малых файлов, а также особенностям применения позиционных и логических файлов удалений в транзакционных озёрах данных. В работе рассмотрены основные стратегии обслуживания метаданных и оптимизации Iceberg-таблиц, необходимые для поддержания высокой эффективности распределённых аналитических систем.
Библиографическое описание
Степанов, Н. С. Архитектура метаданных, статистика и механизмы отброса данных в Apache Iceberg при использовании Apache Spark 3.5 / Н. С. Степанов, Д. А. Тарасов, К. А. Кузьмина. — Текст : непосредственный // Молодой ученый. — 2026. — № 20 (623). — С. 53-58. — URL: https://moluch.ru/archive/623/136792.


Технологическая парадигма построения озёр данных в последние годы существенно изменилась благодаря развитию открытых табличных форматов. Одним из наиболее значимых решений в этой области стал Apache Iceberg, представляющий собой архитектурный подход к управлению данными на уровне отдельных файлов, а не директорий. Такой подход обеспечивает изоляцию снимков (Snapshot Isolation), поддержку эволюции схемы данных и независимость от конкретного вычислительного движка. В сочетании с Apache Spark версии 3.5 и выше Iceberg версии 1.8+ фактически превратился в стандарт для высоконагруженных аналитических платформ.

При этом производительность подобной инфраструктуры напрямую определяется эффективностью механизмов сбора, хранения и использования статистики о данных. Существенную роль играет способность планировщика запросов минимизировать объёмы операций ввода-вывода за счёт интеллектуального отброса нерелевантных данных. В связи с этим особую актуальность приобретает анализ того, каким образом Iceberg организует хранение метаданных, как Spark использует накопленную статистику и какие факторы приводят к деградации производительности.

Настоящая работа посвящена исследованию архитектуры хранения статистики в Apache Iceberg, анализу механизмов многоуровневого отброса данных (Data Pruning), а также рассмотрению особенностей применения файлов удалений (Delete Files). Отдельное внимание уделяется проблемам производительности, возникающим при отсутствии статистики либо при чрезмерном накоплении метаданных.

1 Архитектура хранения статистики: симбиоз Parquet и Iceberg

Apache Iceberg не является самостоятельным форматом хранения данных в традиционном понимании. Он представляет собой слой управления метаданными, работающий поверх физических форматов хранения, наиболее распространённым из которых является Apache Parquet. В результате система хранения строится по двухуровневому принципу: физический уровень отвечает за размещение данных и базовой статистики внутри файлов, а логический уровень обеспечивает централизованное управление метаданными на уровне всей таблицы.

Физический уровень: внутренняя статистика Apache Parquet

Apache Parquet представляет собой колоночный формат хранения, ориентированный на высокую степень сжатия и минимизацию объёма считываемых данных. Одним из ключевых преимуществ формата является его самоописываемость: каждый файл содержит не только данные, но и схему, а также статистические сведения о содержимом. Эта информация располагается в футере (footer) файла, что позволяет вычислительным системам обращаться к статистике без необходимости последовательного чтения всего содержимого.

Внутренняя структура Parquet основана на разделении данных на группы строк (Row Groups), типичный размер которых составляет от 64 до 128 МБ. Для каждой колонки внутри такой группы автоматически вычисляются минимальные и максимальные значения, количество null-элементов и общее число записей. Дополнительно современные реализации поддерживают Column Indexes — индексы столбцов на уровне отдельных страниц данных (Data Pages), размер которых обычно составляет около 1 МБ. Ещё одним механизмом ускорения фильтрации выступают фильтры Блума (Bloom Filters), позволяющие с высокой вероятностью определить отсутствие конкретного значения в блоке данных.

Несмотря на высокую эффективность подобной статистики, её основное ограничение заключается в локальности. Spark может использовать статистику Parquet только после открытия файла и чтения его футера. В условиях озёр данных, содержащих миллионы файлов в распределённом облачном хранилище, подобная операция приводит к значительным накладным расходам на сетевые обращения. В результате возникает эффект «узкого места метаданных» (metadata bottleneck), при котором время планирования запросов начинает превышать время непосредственного выполнения вычислений.

Логический уровень: перенос статистики в метаданные Iceberg

Для устранения проблемы массового чтения футеров Parquet Apache Iceberg поднимает критически важную статистику на уровень логической таблицы. Во время записи данных система извлекает статистические сведения из файлов Parquet и агрегирует их в собственных метаданных. Архитектура метаданных Iceberg организована в виде направленного ациклического графа (DAG), что позволяет Spark строить планы выполнения запросов, практически не обращаясь к физическим данным.

Основными компонентами метаданных Iceberg являются Metadata File, Manifest List и Manifest File. Их назначение и роль в архитектуре хранения статистики представлены в таблице 1.

Таблица 1

Компоненты метаданных Iceberg

Компонент

Формат

Роль в хранении статистики

Metadata File

JSON

Хранит глобальную схему таблицы, конфигурации партиционирования и идентификатор текущего снимка. Не содержит статистики по данным.

Manifest List

Avro

Агрегирует все манифесты снимка и хранит диапазоны значений ключей партиционирования (min/max bounds).

Manifest File

Avro

Отслеживает файлы данных Parquet и дублирует статистику из футеров: min/max, количество null/NaN, число записей для каждой колонки.

Благодаря подобной архитектуре Iceberg устраняет необходимость прямого листинга директорий хранилища и позволяет Spark выполнять фильтрацию файлов на уровне метаданных. Это особенно важно в распределённых облачных системах, где стоимость операций доступа к объектному хранилищу может становиться критическим фактором производительности.

Формат Puffin и расширенная статистика

Базовая статистика min/max эффективна при фильтрации диапазонов, однако её недостаточно для работы Cost-Based Optimizer (CBO), которому необходима информация о кардинальности данных. Для решения данной задачи в экосистеме Iceberg был разработан формат Puffin — специализированный бинарный контейнер для хранения расширенной статистики.

В качестве механизма оценки количества уникальных значений (NDV, Number of Distinct Values) используется алгоритм Theta Sketch из библиотеки Apache DataSketches. В отличие от HyperLogLog, данный алгоритм поддерживает операции пересечения множеств, что особенно важно при оценке селективности предикатов и оптимизации соединений таблиц.

Статистика NDV формируется посредством процедуры system.compute_table_stats и используется Spark для определения наиболее эффективного порядка выполнения операций Join. Наличие актуальных Puffin-файлов существенно повышает качество решений, принимаемых оптимизатором Catalyst.

2 Деградация производительности и влияние статистики

Проблемы производительности в связке Apache Iceberg и Spark 3.5 проявляются неоднородно. В одних случаях система страдает из-за недостатка статистической информации, в других — из-за чрезмерного накопления метаданных и фрагментации файлов. Оба сценария приводят к существенному ухудшению эффективности выполнения запросов.

Отсутствие статистики и ошибки Cost-Based Optimization

Оптимизатор Catalyst использует механизм Cost-Based Optimization при включённом параметре spark.sql.cbo.enabled=true. Если статистика NDV отсутствует, Spark вынужден опираться исключительно на общее количество строк, указанное в манифестах. В подобных условиях оптимизатор часто выбирает неоптимальный порядок соединений.

Например, при выполнении запроса, объединяющего таблицу фактов объёмом 100 млн строк и две таблицы измерений размером 2 млн и 1 млн строк соответственно, Catalyst может принять решение сначала соединить две меньшие таблицы. Формально такой выбор выглядит логичным, однако при низкой кардинальности ключей соединения возникает эффект, близкий к декартову произведению. В результате объём промежуточных данных возрастает до сотен миллионов записей, что приводит к масштабному Shuffle, переполнению памяти исполнителей и возникновению ошибок типа OutOfMemory.

Даже при наличии Puffin-файлов интеграция Spark 3.5 с Iceberg не всегда работает идеально. В ряде случаев Cost-Based Optimizer некорректно извлекает статистику distinct_count из файлов.stat, несмотря на успешное чтение аналогичной статистики из стандартных Parquet-таблиц. Хотя Adaptive Query Execution частично компенсирует подобные проблемы, начальный этап планирования всё равно остаётся субоптимальным.

Инфляция метаданных и фрагментация

Не менее серьёзной проблемой является неконтролируемый рост объёма метаданных. В условиях потоковой обработки данных Spark Structured Streaming может генерировать десятки тысяч файлов ежемесячно. Например, при записи данных с минутным интервалом количество файлов за месяц превышает 43 000. В подобных условиях затраты на чтение манифестов и применение фильтров становятся настолько высокими, что стадия планирования начинает занимать больше времени, чем непосредственное выполнение вычислений.

Дополнительные сложности возникают из-за фрагментации манифестов. Если диапазоны партиций внутри Manifest Files существенно перекрываются, глобальный механизм отброса данных теряет эффективность. Ещё одной проблемой становится раздувание истории снимков: при отсутствии очистки файл metadata.json может достигать сотен мегабайт, создавая значительную нагрузку на драйвер Spark при десериализации.

Основные причины деградации производительности и соответствующие стратегии предотвращения представлены в таблице 2.

Таблица 2

Причины деградации и стратегии предотвращения

Причина

Симптомы

Фаза Spark

Стратегия предотвращения

Отсутствие NDV

Неоптимальный Join Reordering, чрезмерный Shuffle

Execution

Использование compute_table_stats для генерации Puffin-файлов

Малые файлы

Высокая задержка I/O, длительный запуск Job

Planning / Scan

Компактизация через rewrite_data_files

Фрагментация манифестов

Снижение эффективности отброса партиций

Planning

Дефрагментация через rewrite_manifests

Раздувание истории

Рост времени чтения метаданных, перегрузка драйвера

Catalog

Очистка с помощью expire_snapshots и remove_orphan_files

Для предотвращения деградации применяются специализированные процедуры обслуживания. Генерация Puffin-файлов посредством compute_table_stats позволяет поддерживать актуальную статистику NDV. Процедура rewrite_data_files используется для компактизации мелких файлов, rewrite_manifests — для дефрагментации Avro-манифестов, а expire_snapshots и remove_orphan_files — для очистки устаревших версий таблиц и удаления неиспользуемых файлов.

3 Механизмы многоуровневого отброса данных (Data Pruning)

Высокая производительность Iceberg-таблиц достигается за счёт многоуровневого механизма отброса данных, позволяющего избегать чтения нерелевантных файлов и блоков ещё на этапе планирования запроса. По мере продвижения предикатов от драйвера к исполнителям уровень детализации анализа последовательно увеличивается.

Отброс списков манифестов (Manifest List Pruning)

Первый уровень отброса данных выполняется на драйвере и основан на анализе Manifest List — компактного Avro-файла размером всего в несколько десятков килобайт. Планировщик Spark считывает диапазоны партиций для каждого манифеста и исключает те из них, диапазоны которых не пересекаются с условием запроса.

Ключевым преимуществом данного механизма является поддержка скрытого партиционирования (Hidden Partitioning). Пользователю не требуется явно указывать производный столбец партиции в SQL-запросе: Iceberg самостоятельно вычисляет трансформацию и применяет её к диапазонам партиций. В корректно спроектированных таблицах этот уровень способен отсекать до 95 % метаданных практически мгновенно.

Отброс файлов манифестов (Manifest File Pruning)

На следующем этапе Spark открывает прошедшие фильтрацию Manifest Files и анализирует статистику отдельных файлов данных. Для каждого файла проверяются минимальные и максимальные значения колонок, количество null-значений и другие характеристики.

Эффективность данного механизма напрямую зависит от физической организации данных. При сортировке таблиц по колонкам фильтрации, например, с использованием ORDER BY или Z-Ordering, диапазоны min/max становятся существенно уже, что позволяет отбрасывать большую часть файлов без обращения к физическим данным. Если же данные распределены хаотично, диапазоны значений начинают сильно перекрываться, а эффективность отброса резко снижается.

Отброс групп строк (Row Group Pruning)

Файлы, не исключённые на уровне метаданных Iceberg, передаются исполнителям Spark для физического чтения. Векторизованный Parquet-читатель обращается к футеру файла и анализирует статистику каждой группы строк.

Например, если запрос содержит условие amount > 100, а максимальное значение в конкретной Row Group равно 50, соответствующая группа строк полностью пропускается. Благодаря этому Spark избегает декомпрессии и материализации ненужных данных, снижая нагрузку на процессор и подсистему памяти.

Отброс страниц Parquet (Page Index Pruning)

Наиболее глубокий уровень оптимизации связан с использованием Column Indexes в формате Parquet. Данный механизм позволяет анализировать статистику отдельных страниц данных размером около 1 МБ внутри группы строк.

При наличии локальной сортировки Spark способен отбрасывать отдельные страницы без чтения всей группы строк. В сочетании с фильтрами Блума подобный подход обеспечивает практически минимально возможный объём физического сканирования данных.

4 Применение файлов удалений (Delete Files)

В транзакционных озёрах данных операции UPDATE, DELETE и MERGE INTO реализуются двумя основными подходами: Copy-on-Write (CoW) и Merge-on-Read (MoR). В первом случае происходит полная перезапись файлов данных, тогда как во втором используются специализированные файлы удалений. Spark 3.5 ориентирован преимущественно на использование Merge-on-Read как более эффективного механизма для потоковых сценариев обработки данных.

Позиционные удаления (Positional Deletes)

В спецификации Iceberg v2 были введены позиционные файлы удалений. Они представляют собой Parquet-файлы, содержащие пары значений: путь к файлу данных и номер строки внутри него.

Во время выполнения запроса Spark сопоставляет файлы данных с соответствующими файлами удалений. На стороне исполнителей формируется битовая маска (bitmap), используемая в процессе векторизованного чтения Parquet. Если номер строки присутствует в маске, запись отбрасывается без материализации.

Однако накопление большого количества позиционных файлов удалений приводит к серьёзной деградации производительности. Например, наличие 10 000 файлов удалений вынуждает Spark выполнять тысячи дополнительных операций открытия файлов, чтения метаданных и построения структур в памяти. Без регулярной компактизации производительность системы начинает снижаться экспоненциально.

Удаления по равенству (Equality Deletes)

При обработке CDC-потоков, когда физическое местоположение строки заранее неизвестно, применяются Equality Deletes. Вместо хранения позиции строки такие файлы содержат логические условия удаления, например id = 50.

Механизм работы Equality Deletes отличается от позиционных удалений. Spark формирует из файла удалений хеш-таблицу, после чего базовые данные проходят через Hash Join с операцией Anti-Join. Если ключ строки присутствует в таблице удалений, соответствующая запись исключается из результата.

Подобный подход с использованием Equality Deletes наиболее характерен для сценариев потоковой обработки (Streaming). При записи данных в реальном времени основной приоритет отдается пропускной способности записи. Это избавляет систему от необходимости выполнять дорогостоящую операцию поиска в существующих данных во время записи для поиска строки удаления.

Стриминг мгновенно фиксирует удаление, создавая небольшой файл со списком ключей.

5 Интеграция статистики и оптимизация соединений в Spark 3.5

Adaptive Query Execution (AQE)

Начиная с версии Spark 3.2, механизм Adaptive Query Execution включён по умолчанию и играет важную роль в компенсации ошибок предварительного планирования. В отличие от статического Cost-Based Optimization, AQE способен динамически корректировать план выполнения уже в процессе работы.

В интеграции с Iceberg данный механизм предоставляет ряд преимуществ. Во-первых, AQE автоматически объединяет мелкие партиции после Shuffle. Во-вторых, система способна выявлять перекосы распределения данных (Skew Join Optimization) и перераспределять «тяжёлые» ключи. В-третьих, Spark может адаптивно изменять тип соединения, например, переключаясь с Sort-Merge Join на Broadcast Hash Join при обнаружении небольшого фактического размера одной из таблиц.

Тем не менее AQE не устраняет все проблемы производительности. В сценариях интенсивной потоковой записи даже адаптивное планирование часто требует дополнительной ручной настройки и обслуживания метаданных.

Storage Partitioned Joins (SPJ)

Одной из наиболее эффективных технологий Spark 3.5 и Iceberg 1.8+ является механизм Storage Partitioned Join (SPJ), позволяющий полностью устранить Shuffle при соединении таблиц.

Если две таблицы физически бакетированы по ключу соединения, Spark назначает обработку соответствующих сегментов одному исполнителю, выполняя локальное соединение без перераспределения данных по сети. Для использования данного механизма необходимо активировать параметры spark.sql.sources.v2.bucketing.enabled=true и spark.sql.iceberg.planning.preserve-data-grouping=true. Последний параметр предотвращает разделение файлов одной физической партиции между различными задачами чтения.

Использование SPJ позволяет значительно снизить сетевые накладные расходы и ускорить выполнение сложных аналитических запросов.

Выводы и стратегии обслуживания метаданных

Архитектура статистики в экосистеме Apache Spark 3.5 и Apache Iceberg представляет собой компромисс между затратами на управление метаданными и преимуществами интеллектуальной оптимизации чтения. При отсутствии статистики Cost-Based Optimizer теряет возможность корректно планировать соединения, что приводит к взрывному росту промежуточных данных. С другой стороны, чрезмерное накопление метаданных и мелких файлов вызывает деградацию стадии планирования запросов.

Для поддержания высокой производительности необходим системный подход к обслуживанию озера данных. Одним из ключевых мероприятий является регулярная компактизация данных и позиционных файлов удалений посредством процедур rewrite_data_files и rewrite_position_delete_files. Это позволяет объединять мелкие файлы в крупные блоки размером 128–512 МБ и восстанавливать эффективность механизмов Data Pruning.

Не менее важной задачей выступает дефрагментация манифестов с помощью процедуры rewrite_manifests, устраняющей перекрытие диапазонов значений и повышающей эффективность глобального отброса данных. Для предотвращения разрастания истории таблиц используются процедуры expire_snapshots и remove_orphan_files, обеспечивающие удаление устаревших версий и неиспользуемых файлов.

Наконец, критически важным условием корректной работы Cost-Based Optimizer является регулярное обновление расширенной статистики посредством compute_table_stats. Поддержание актуальных Puffin-файлов с Theta Sketches позволяет Spark более точно оценивать селективность запросов и выбирать оптимальные стратегии выполнения соединений.

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

Литература:

  1. Zaharia M., Chowdhury M., Das T. et al. Apache Spark: A Unified Engine for Big Data Processing // Communications of the ACM. — 2016. — Vol. 59, № 11. — P. 56–65.
  2. Melnik S., Gubarev A., Long J. et al. Dremel: Interactive Analysis of Web-Scale Datasets // Proceedings of the VLDB Endowment. — 2010. — Vol. 3, № 1–2. — P. 330–339.
  3. Apache Iceberg Documentation [Электронный ресурс]. — Режим доступа: https://iceberg.apache.org/docs/latest/ (дата обращения: 15.05.2026).
  4. Apache Parquet Documentation [Электронный ресурс]. — Режим доступа: https://parquet.apache.org/docs/ (дата обращения: 15.05.2026).
  5. Armbrust M., Ghodsi A., Xin R. et al. Delta Lake: High-Performance ACID Table Storage over Cloud Object Stores // Proceedings of the VLDB Endowment. — 2020. — Vol. 13, № 12. — P. 3411–3424.
  6. Yogev Y. Making Sense of Apache Iceberg Statistics [Электронный ресурс] // Medium. — Режим доступа: https://www.ryft.io/blog/making-sense-of-apache-iceberg-statistics/ (дата обращения: 15.05.2026).
  7. Adaptive Query Execution: Speeding Up Spark SQL at Runtime [Электронный ресурс] // Databricks Blog. — Режим доступа: https://www.databricks.com/blog/2020/05/29/adaptive-query-execution-speeding-up-spark-sql-at-runtime.html/ (дата обращения: 15.05.2026).
  8. Puffin Specification [Электронный ресурс] // Apache Iceberg Documentation. — Режим доступа: https://iceberg.apache.org/puffin-spec/ (дата обращения: 15.05.2026).
  9. Optimization Strategies for Iceberg Tables [Электронный ресурс] // Cloudera Blog. — Режим доступа: https://www.cloudera.com/blog/technical/optimization-strategies-for-iceberg-tables.html/ (дата обращения: 15.05.2026).
  10. Best Practices for Optimizing Apache Iceberg Performance [Электронный ресурс] // Starburst. — Режим доступа: https://www.starburst.io/blog/best-practices-for-optimizing-apache-iceberg-performance/ (дата обращения: 15.05.2026).
Можно быстро и просто опубликовать свою научную статью в журнале «Молодой Ученый». Сразу предоставляем препринт и справку о публикации.
Опубликовать статью

Молодой учёный