Apache Iceberg. Метатаблицы
Рентген для данных
Содержание
Метатаблицы Iceberg — это как рентген для ваших данных: можно заглянуть внутрь, не вскрывая пациента. Только не удивляйтесь, если обнаружите, что некоторые файлы ведут себя странно — это нормально для данных, которые живут своей жизнью.
Что такое метатаблицы и зачем они нужны
Метатаблицы Iceberg — это системные таблицы, которые дают вам доступ к внутреннему состоянию таблицы Iceberg через обычный SQL. Вместо того чтобы копаться в JSON-файлах метаданных или писать сложные скрипты, вы можете просто выполнить SELECT и увидеть, что происходит внутри таблицы.
-- Обычная таблицаSELECT * FROM sales; -- Метаданные таблицыSELECT * FROM sales.history; -- история измененийSELECT * FROM sales.snapshots; -- информация о снэпшотахSELECT * FROM sales.files; -- файлы с даннымиSELECT * FROM sales.manifests; -- файлы манифестовSELECT * FROM sales.partitions; -- статистика партицийSELECT * FROM sales.refs; -- ветки и тегиSELECT * FROM sales.entries; -- изменения свойствSELECT * FROM sales.metadata_log_entries; -- изменения свойств
Зачем это нужно?
- Отладка производительности — понять, почему запросы стали медленнее
- Анализ файлов — увидеть распределение файлов по партициям, их размеры, количество
- Мониторинг здоровья — отслеживать рост таблицы, количество снапшотов, состояние манифестов
- Планирование обслуживания — определить, какие партиции нуждаются в компактификации
Метатаблицы доступны через синтаксис table_name.metadata_table_name. Например, если ваша таблица называется orders, то метатаблица снапшотов будет orders.snapshots. Рассмотрим на примере из прошлого упражнения.
`snapshots` — снапшоты таблицы
Показывает все снапшоты таблицы: их ID, родительские снапшоты, временные метки и путь к файлу манифест-листа.
SELECT *FROM finance.transactions.snapshotsORDER BY committed_at DESCLIMIT 1;
| Поле | Значение |
|---|---|
| committed_at | 2026-06-14 11:18:40.953 |
| snapshot_id | 3007366648374978862 |
| parent_id | 1739356557666905284 |
| operation | overwrite |
| manifest_list | s3://warehouse/finance/transactions/metadata/snap-3007366648374978862-1-4e1273c4-19a3-40f2-ab58-212bb6e8401b.avro |
| summary | { "added-data-files": "1", "added-files-size": "2196", "added-records": "4", "app-id": "local-1781435738405", "changed-partition-count": "1", "deleted-data-files": "4", "deleted-records": "4", "engine-name": "spark", "engine-version": "3.5.5", "iceberg‑version": "Apache Iceberg 1.8.1 (commit 9ce0fcf0af7becf25ad9fc996c3bad2afdcfd33d)", "removed-files-size": "8260", "spark.app.id": "local-1781435738405", "total-data-files": "9", "total-delete-files": "0", "total-equality-deletes": "0", "total-files-size": "18539", "total-position-deletes": "0", "total-records": "12" } |
Типичные случаи использования:
- Просмотр истории изменений таблицы
- Понимание, какие операции (append, replace, delete) происходили
- Поиск конкретного снапшота для time travel
`manifests` — манифесты
Даёт информацию о каждом файле манифеста: его путь, тип, количество добавленных и удалённых файлов, размер, время создания.
SELECT *FROM finance.transactions.manifestsLIMIT 1;
| Поле | Значение |
|---|---|
| content | 0 |
| path | s3://warehouse/finance/transactions/metadata/4e1273c4-19a3-40f2-ab58-212bb6e8401b-m1.avro |
| length | 7418 |
| partition_spec_id | 0 |
| added_snapshot_id | 3007366648374978862 |
| added_data_files_count | 1 |
| existing_data_files_count | 0 |
| deleted_data_files_count | 0 |
| added_delete_files_count | 0 |
| existing_delete_files_count | 0 |
| deleted_delete_files_count | 0 |
| partition_summaries | [] |
Типичные случаи использования:
- Понимание распределения данных по манифестам
- Выявление манифестов с большим количеством мелких файлов
- Отслеживание эффективности компактификации
`files` — файлы данных
Пожалуй, самая полезная метатаблица. Показывает детальную информацию о каждом файле данных: содержимое, партицию, размер, количество записей, форматы, статистику по колонкам.
SELECT *FROM finance.transactions.filesLIMIT 1;
| Поле | Значение |
|---|---|
| content | 0 |
| file_path | s3://warehouse/finance/transactions/data/00000-17-c6bbfe6a-aba4-4aac-8968-54cedc04f16c-0-00001.parquet |
| file_format | PARQUET |
| spec_id | 0 |
| record_count | 4 |
| file_size_in_bytes | 2196 |
| column_sizes | {1:64,2:95,3:57,4:68,5:163,6:42} |
| value_counts | {1:4,2:4,3:4,4:4,5:4,6:4} |
| null_value_counts | {1:0,2:0,3:0,4:0,5:0,6:0} |
| nan_value_counts | {} |
| lower_bounds | {1:�,2:d,3:�N,4:�,5:Депозит нового к,6:} |
| upper_bounds | {1:�,2:g,3:�N,4:�`,5:Получен возврат,6:} |
| key_metadata | NULL |
| split_offsets | [4] |
| equality_ids | NULL |
| sort_order_id | 0 |
| referenced_data_file | NULL |
| content_offset | NULL |
| content_size_in_bytes | NULL |
| readable_metrics | { "account_id": { "column_size":95, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":100, "upper_bound":103 }, "amount": { "column_size":68, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":-750.00, "upper_bound":15000.00 }, "description": { "column_size":163, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":"Депозит нового к", "upper_bound":"Получен возврат" }, "transaction_date": { "column_size":57, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":2025-02-10, "upper_bound":2025-02-12 }, "transaction_id": { "column_size":64, "value_count":4, "null_value_count":0,"nan_value_count":null, "lower_bound":1009, "upper_bound":1012 }, "verified": { "column_size":42, "value_count":4, "null_value_count":0,"nan_value_count":null, "lower_bound":true, "upper_bound":true } } |
Типичные случаи использования:
- Анализ распределения размеров файлов
- Поиск слишком маленьких или слишком больших файлов
- Понимание, какие партиции содержат больше всего данных
- Отладка проблем с партицированием
`partitions` — партиции
Показывает информацию о партициях таблицы: их спецификацию, количество файлов, записей, размер.
SELECT *FROM finance.transactions.partitionsLIMIT 1;
| Поле | Значение |
|---|---|
| record_count | 12 |
| file_count | 9 |
| total_data_file_size_in_bytes | 18539 |
| position_delete_record_count | 0 |
| position_delete_file_count | 0 |
| equality_delete_record_count | 0 |
| equality_delete_file_count | 0 |
| last_updated_at | 2026-06-14 11:18:40.953 |
| last_updated_snapshot_id | 3007366648374978862 |
Типичные случаи использования:
- Мониторинг роста партиций
- Выявление несбалансированных партиций
- Планирование обслуживания
`refs` — ссылки (ветки и теги)
Показывает все ветки и теги таблицы, их тип, связанный снапшот и максимальный возраст ссылки.
SELECT *FROM finance.transactions.refsLIMIT 1;
| Поле | Значение |
|---|---|
| name | feb-2025-close |
| type | TAG |
| snapshot_id | 3007366648374978862 |
| max_reference_age_in_ms | NULL |
| min_snapshots_to_keep | NULL |
| max_snapshot_age_in_ms | NULL |
Типичные случаи использования:
- Просмотр всех веток и тегов таблицы
- Понимание, какие снапшоты защищены от удаления
- Отладка политик удержания
`entries` — записи манифеста
Предоставляет детальную информацию на уровне отдельных записей в манифестах: статус (добавлен/удалён), данные файла, последовательный номер, номер снапшота.
SELECT *FROM finance.transactions.entriesLIMIT 1;
| Поле | Значение |
|---|---|
| status | 1 |
| snapshot_id | 3007366648374978862 |
| sequence_number | 4 |
| file_sequence_number | 4 |
| data_file | { "content":0, "file_path":"s3://warehouse/finance/transactions/data/00000-17-c6bbfe6a-aba4-4aac-8968-54cedc04f16c-0-00001.parquet", "file_format":"PARQUET", "spec_id":0, "record_count":4, "file_size_in_bytes":2196, "column_sizes": { 1:64, 2:95, 3:57, 4:68, 5:163, 6:42 }, "value_counts": { 1:4, 2:4, 3:4, 4:4, 5:4, 6:4 }, "null_value_counts": { 1:0, 2:0, 3:0, 4:0, 5:0, 6:0 }, "nan_value_counts": { }, "lower_bounds": { 1:�, 2:d, 3:�N, 4:�, 5:Депозит нового к, 6: }, "upper_bounds": { 1:�, 2:g, 3:�N, 4:�`, 5:Получен возврат, 6: }, "key_metadata":null, "split_offsets":[4], "equality_ids":null, "sort_order_id":0, "referenced_data_file":null, "content_offset":null, "content_size_in_bytes":null } |
| readable_metrics | { "account_id": { "column_size":95, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":100, "upper_bound":103 }, "amount": { "column_size":68, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":-750.00, "upper_bound":15000.00 }, "description": { "column_size":163, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":"Депозит нового к", "upper_bound":"Получен возврат" }, "transaction_date": { "column_size":57, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":2025-02-10, "upper_bound":2025-02-12 }, "transaction_id": { "column_size":64, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":1009, "upper_bound":1012 }, "verified": { "column_size":42, "value_count":4, "null_value_count":0, "nan_value_count":null, "lower_bound":true, "upper_bound":true } } |
Типичные случаи использования:
- Детальный аудит изменений
- Понимание, какие файлы были добавлены или удалены в конкретном снапшоте
- Отладка проблем с дублированием данных
Практические примеры
Мониторинг роста таблицы
-- Почему моя таблица внезапно вырослаWITH daily_growth AS ( SELECT DATE(committed_at) as date, SUM(CAST(summary['added-files-size'] AS BIGINT))/1024/1024/1024 as gb_added FROM sales.snapshots WHERE committed_at > current_date - 7 GROUP BY 1)SELECT * FROM daily_growthWHERE gb_added > 100;
| date | gb_added |
|---|---|
| 2025-11-27 | 342.7 |
| 2025-11-28 | 387.2 |
| 2025-11-29 | 156.8 |
| 2025-11-30 | 421.5 |
| 2025-12-01 | 395.1 |
| 2025-12-02 | 289.4 |
Этот запрос покажет ежедневный рост таблицы: сколько снапшотов создаётся и сколько данных добавляется каждый день.
Поиск партиций, нуждающихся в обслуживании
-- Каким партициям требуется сжатие?SELECT partition, file_count, CASE WHEN file_count > 100 THEN 'NEEDS COMPACTION' WHEN AVG(file_size_in_bytes)/1024/1024 < 10 THEN 'SMALL FILES' ELSE 'OK' END as actionFROM sales.filesGROUP BY partitionHAVING file_count > 100 OR AVG(file_size_in_bytes)/1024/1024 < 10;
| partition | file_count | action |
|---|---|---|
| {"sale_date_month": 669, "region": "US"} | 247 | NEEDS COMPACTION |
| {"sale_date_month": 670, "region": "APAC"} | 183 | NEEDS COMPACTION |
| {"sale_date_month": 667, "region": "EMEA"} | 156 | NEEDS COMPACTION |
| {"sale_date_month": 668, "region": "US"} | 128 | NEEDS COMPACTION |
| {"sale_date_month": 665, "region": "LATA"} | 87 | SMALL FILES |
| {"sale_date_month": 671, "region": "APAC"} | 73 | SMALL FILES |
| {"sale_date_month": 662, "region": "EMEA"} | 52 | SMALL FILES |
Этот запрос находит партиции, в которых слишком много мелких файлов — кандидатов на компактификацию. Для этого таблица конечно же должна быть партицирована.
Отслеживание веток и тегов
-- ОтслеиSELECT name, type, snapshot_id, max_reference_age_in_ms/86400000 as retention_daysFROM sales.refs
| name | type | snapshot_id | retention_days |
|---|---|---|---|
| main | BRANCH | 8829603393873253991 | null |
| staging | BRANCH | 8829603393873253987 | 7.0 |
| backup_2024_q4 | TAG | 8829603393873253945 | 90.0 |
| pre_migration | TAG | 8829603393873253921 | 30.0 |
| dev_feature_x | BRANCH | 8829603393873253978 | 3.0 |
| audit_snapshot | TAG | 8829603393873253889 | 365.0 |
Показывает все ветки и теги с привязкой к снапшотам и датам их создания.
Отладка и советы для продакшена
Давайте применим эти таблицы на практике для решения некоторых реально звучащих проблем.
Первый запрос: ваша таблица выросла на 500 гигабайт за ночь. Да, кажется плохо. Что случилось? Этот запрос сразу показывает, в какой день был необычный рост. И внезапно да, пятница очень большая, суббота очень большая, воскресенье немного меньше, но вы можете увидеть начало динамики праздничного сезона. Так что, возможно, это не что‑то сломанное в пайплайне, а просто очень удачный год. Но это даёт вам некоторое понимание.
Второй запрос: какие партиции нуждаются в обслуживании? Вместо догадок вы можете получить точный список партиций, у которых слишком много файлов и которые, возможно, нуждаются в компактификации. И мы определим это здесь как более 100 файлов на партицию или файлы, которые слишком малы (средний размер меньше 10 мегабайт). Это может быть проблемой. Так что, если вы просмотрите этот запрос, у нас есть случай, когда количество файлов больше 100 и средний размер меньше 10 мегабайт. Это называется «мелкие файлы», и мы получаем эту хорошую колонку action: needs_compaction_small_files. Это небольшой анализ партиций прямо из одного запроса.
Третий запрос: отслеживайте ваши ветки и теги с их политиками удержания. Вы действительно можете запускать эти запросы ежедневно в продакшене. Расследования, которые занимали часы, теперь занимают минуты. Вы можете просто заметить эти вещи. Те, которые подлежат очистке, — всё из метатаблицы refs.
Советы по использованию метатаблиц в продакшене
Несколько вещей:
- Создавайте представления (views) для запросов, которые вы запускаете часто. Например, проверки здоровья, тренды роста, анализ партиций — это удобная вещь, которую стоит иметь в своём арсенале.
- Настраивайте алерты, когда количество файлов достигает порогов. Вы можете легко получить количество файлов из метатаблиц.
- Автоматизируйте ежедневные проверки здоровья. Мы видели несколько примеров этого.
- Документируйте то, что находите. Это отлично подходит для планирования мощностей. Вы сможете легко получить эти результаты и поделиться ими.
И эти запросы — очень важный момент — дёшевые. Они читают крошечные файлы метаданных, а не ваши фактические данные. Так что это не будет дорогостоящими операциями. И действительно, вам стоит рассмотреть возможность сделать их частью вашего ежедневного workflow.
Метатаблицы дают вам видимость того, что происходит внутри Iceberg. Сложная отладка превращается в простой SQL. В некоторых случаях — умеренно интересный SQL, но вы можете это сделать. Это то, что вы делаете. Это база данных. Нет никаких догадок о состоянии таблицы — просто запросите метаданные.
И на основе некоторых открытий, которые мы делаем, глядя на метаданные таблицы, нам, возможно, придётся выполнить некоторое обслуживание таблиц, на которое мы посмотрим дальше.
«Метатаблицы Iceberg — это как рентген для ваших данных: можно заглянуть внутрь, не вскрывая пациента. Только не удивляйтесь, если обнаружите, что некоторые файлы ведут себя странно — это нормально для данных, которые живут своей жизнью.»
На этом пока всё
Вы завершили пятую часть курса Apache Iceberg! Вы освоили тегирование и ветвление — Git‑подобный workflow с тегами, ветками, fast‑forward мержами и Write‑Audit‑Publish, а также научились анализировать внутреннее состояние таблиц через системные метатаблицы. Отличный прогресс!
Что будет дальше? В шестой, заключительной части курса мы перейдём к финальным темам:
- Обслуживание таблиц — удаление старых снапшотов, компактификация, очистка метаданных.
- Движки запросов и экосистема — обзор Spark, Flink, Trino, облачных сервисов и Python.
Чтобы не пропустить выход новых уроков:
- Подпишитесь на канал SubQuery в Telegram — там мы анонсируем все обновления курса.
- А чтобы ТОЧНО не пропустить, присоединяйтесь к каналу в MAX 🤭
Спасибо, что учитесь с нами! 🚀