Learning Platform
Глоссарий Troubleshooting
Урок 15.05 · 40 мин
Продвинутый
Apache PaimonCompactionDeletion VectorsZ-OrderData SkippingTagSnapshotTime TravelBloom FilterMin-Max Statistics

Data Management + Optimization

В предыдущих уроках мы разобрали архитектуру хранения Paimon: LSM-деревья (Урок 01), merge engine’ы (Урок 02), changelog producer (Урок 03) и bucket/partition design (Урок 04). Теперь — как управлять данными в production: компакция, deletion vectors, z-order, data skipping и snapshot lifecycle.

Компакция: управление LSM-деревом

Компакция — фундаментальная операция LSM-дерева: объединение sorted runs для уменьшения read amplification. Paimon запускает компакцию автоматически, но параметры критически влияют на производительность.

Триггер компакции: когда запускается merge?
num-sorted-run.compaction-triggerПо умолчанию: 5. Когда количество sorted runs в бакете достигает этого порога — запускается компакция. Чем ниже значение, тем чаще компакция (больше write amplification), но лучше read performance (меньше sorted runs для merge). Чем выше — реже компакция, но read замедляется.
компакция объединяет sorted runs

5 sorted runs Read: merge 5 потоков

До компакции: 5 sorted runs в бакете. Каждый sorted run — результат одного flush из MemTable. Point lookup требует проверки всех 5 runs (merge на чтении). Range scan мержит 5 потоков.
compact

1-2 sorted runs Read: merge 1-2 потока

После компакции: sorted runs объединены в меньшее количество (или один). Read performance улучшается — меньше потоков для merge. Данные физически перезаписаны в новые SST-файлы (Parquet).

Три ключевых параметра компакции

Параметры компакции: размер файлов и частота
compaction.min-file-numМинимальное число файлов для запуска компакции внутри sorted run. По умолчанию: 5. Если в sorted run меньше файлов — компакция не запускается, даже если sorted run count = trigger. Предотвращает компакцию мелких порций данных.
compaction.max-file-numМаксимальное число файлов для одной компакции. По умолчанию: 50. Ограничивает размер одной компакции — предотвращает слишком длинные операции. Если файлов больше — компакция разбивается на несколько round'ов.
target-file-sizeЦелевой размер SST-файла после компакции. По умолчанию: 128MB. Компакция объединяет мелкие файлы до достижения target. Слишком маленький → много файлов → LIST overhead на object storage. Слишком большой → высокий write amplification при компакции.

Стратегии компакции

Paimon поддерживает две стратегии компакции (подробнее в Уроке 01):

Universal vs Sorted-Run компакция
Universal Compaction (по умолчанию)Объединяет все sorted runs в один. Максимальное read performance (1 sorted run → нет merge на чтении). Цена: высокий write amplification — при каждой компакции перезаписываются все данные бакета. Подходит для streaming workloads с умеренным объёмом данных.
Sorted-Run CompactionОбъединяет только соседние sorted runs. Результат: несколько sorted runs с неперекрывающимися ключевыми диапазонами. Меньше write amplification. Read мержит несколько runs, но они не перекрываются → seek, не merge. Для: batch workloads с большими объёмами.
TIP

Для стриминговых таблиц с changelog-producer = lookup или full-compaction, компакция играет двойную роль: уменьшает read amplification И генерирует changelog. Параметр full-compaction.delta-commits контролирует, как часто запускается full compaction для генерации changelog (подробнее в Уроке 03).

Deletion Vectors для Append-Only таблиц

Primary key таблицы обрабатывают удаления через merge engine (tombstone marker в LSM-дереве). Но append-only таблицы (без primary key) не имеют merge engine. Как удалять строки?

Deletion Vector: маркер удалённых строк в Parquet-файле
Parquet File: 1M строкAppend-only Parquet-файл с 1M строк. Файл иммутабелен — перезаписать нельзя. Удаление 100 строк через DELETE WHERE ... Как не перезаписывать весь файл?
DELETE 100 строк
Deletion VectorPaimon создаёт deletion vector — bitmap позиций удалённых строк. Формат: Roaring Bitmap (как DV в Iceberg V3 и Delta Lake Deletion Vectors). Хранится в отдельном файле рядом с data file.
при чтении

Read: data file + DV bitmap Skip строки: bitmap.contains(pos) → O(1) Результат: 999,900 строк

При scan: Paimon читает data file + deletion vector. Для каждой строки: if bitmap.contains(row_position) → skip. O(1) check per row. 999,900 строк возвращаются, 100 — пропущены. Нет перезаписи data file.
NOTE

Deletion vectors в Paimon аналогичны deletion vectors в Delta Lake (DVR — Deletion Vector Reader) и Iceberg V3 (Puffin-based DVs). Все три формата используют Roaring Bitmap для compact representation позиций. Разница — в формате хранения: Paimon хранит DV как отдельный файл рядом с data file, Delta — в _delta_log, Iceberg — в Puffin blob.

Компакция с deletion vectors: периодически Paimon объединяет data file + deletion vector в новый файл без удалённых строк. Это уменьшает overhead при чтении (не нужно проверять bitmap) и освобождает storage.

Z-Order Сортировка

По умолчанию данные в SST-файлах Paimon отсортированы по primary key (для primary key таблиц) или по порядку записи (для append-only). Z-order сортировка меняет порядок данных для улучшения data skipping при запросах по нескольким колонкам.

Z-Order: интерливинг битов для multi-column locality
Без Z-OrderДанные отсортированы по PK (например, user_id). Запрос WHERE region='EU' AND category='electronics' не может использовать PK-сортировку для pruning. Min/max stats на region и category перекрываются во всех файлах → нет data skipping.
z-order rewrite
С Z-OrderZ-order интерливит биты region и category: данные кластеризуются по обоим измерениям одновременно. Файлы содержат компактные диапазоны region+category. Min/max stats становятся плотными → data skipping отсекает 80-90% файлов.
-- Z-Order rewrite для таблицы events
-- Paimon перезаписывает data files с z-order сортировкой
ALTER TABLE events SET ('zorder.columns' = 'region,category');
-- Или через dedicated action:
CALL sys.compact('default.events', 'zorder', 'region,category');
WARNING

Z-order — дорогая операция: полная перезапись данных с новым порядком. Запускайте как batch-задачу в low-traffic окне. Z-order не совместим с primary key сортировкой — для primary key таблиц z-order применяется при компакции к значениям (value columns), но ключи остаются отсортированными для merge.

Data Skipping: Min/Max + Bloom Filter

Data skipping — механизм пропуска файлов и row group’ов при чтении. Paimon поддерживает два уровня:

Data Skipping: два уровня фильтрации
Min/Max Statistics (по умолчанию)Paimon хранит min/max значения для каждой колонки в каждом SST-файле. При scan: если WHERE amount > 1000, а файл имеет max(amount) = 500 → файл пропускается. Работает для всех типов данных. Эффективность зависит от кластеризации данных (z-order улучшает).
Bloom Filter (опционально)Paimon может хранить Bloom filter для указанных колонок. Bloom filter отвечает: 'значение точно НЕ в файле' (no false negative) или 'может быть в файле' (possible false positive). Для equality-запросов (WHERE user_id = 'abc') — пропуск файлов без этого значения.
комбинированный pruning
  1. Partition pruning
  2. Bucket pruning (PK hash)
  3. Min/Max file-level
  4. Bloom filter per-column
  5. Row-group level (Parquet)
Порядок применения: 1) Partition pruning (по partition key). 2) Bucket pruning (по PK hash). 3) Min/max file-level pruning. 4) Bloom filter per-column pruning. 5) Row-group level pruning (Parquet internal). На каждом уровне отсекаются нерелевантные данные.

Включение Bloom filter для конкретных колонок:

-- Включить bloom filter для колонки user_id
ALTER TABLE events SET (
 'fields.user_id.bloom-filter.enabled' = 'true',
 'fields.user_id.bloom-filter.fpp' = '0.01' -- false positive rate 1%
);
TIP

Bloom filter эффективен для high-cardinality колонок с equality-запросами: user_id, order_id, device_id. Для low-cardinality (status, region) min/max statistics достаточно. Для range-запросов (amount BETWEEN 100 AND 200) bloom filter бесполезен — используйте z-order.

Tag Management: именованные snapshot’ы

Snapshot в Paimon — это состояние таблицы в определённый момент: набор manifest’ов → набор SST-файлов → данные. Snapshot’ы создаются автоматически при каждом commit. Tag — это именованный snapshot, защищённый от автоматического удаления.

Snapshot lifecycle: создание → retain → expire

Каждый commit → snapshot Streaming: ~720 snapshot/day

Каждый commit (write, compaction) создаёт новый snapshot. При streaming ingestion: snapshot каждые 1-2 минуты. За сутки: ~720-1440 snapshot'ов. Без lifecycle management — storage растёт бесконечно.

Retain: последние N snapshot’ов snapshot.num-retained.min = 10 snapshot.time-retained = 1h

Snapshot retention: Paimon хранит последние N snapshot'ов (snapshot.num-retained.min / max). Старые snapshot'ы expire — их metadata удаляется, data файлы, не referenced другими snapshot'ами — GC'd. Параметр: snapshot.time-retained (по времени).

Expire: metadata удалена Orphan files → GC

Expired snapshot'ы: metadata удалена. Data файлы: orphan если ни один оставшийся snapshot не ссылается. Orphan files GC — отдельная процедура (аналог Iceberg expire_snapshots + remove_orphan_files).

Tag — это закладка на snapshot, которую expire не тронет:

Tag: именованный snapshot, защищённый от expire
Tag: daily-2025-03-27Tag указывает на snapshot-720 (состояние на конец 27 марта). Даже когда snapshot-720 будет expire'd (прошло больше retention), tag сохраняет ссылку. Data файлы, referenced тегом, не удаляются при GC.
Tag: release-v2.5Tag для фиксации состояния перед релизом. Snapshot ID: 650. Позволяет time-travel к этому моменту в любой момент в будущем. Аналог Iceberg branch или Delta Lake version pin.
Auto Tag (ежедневный)Paimon поддерживает автоматическое создание тегов по расписанию: tag.automatic-creation = process-time, tag.creation-period = daily. Каждый день создаётся тег с timestamp — удобно для daily time-travel без ручного управления.
-- Создать тег вручную
CALL sys.create_tag('default.orders', 'daily-2025-03-27', 720);

-- Автоматические теги: ежедневно
ALTER TABLE orders SET (
 'tag.automatic-creation' = 'process-time',
 'tag.creation-period' = 'daily',
 'tag.num-retained-max' = '30' -- хранить последние 30 дней
);

-- Удалить тег
CALL sys.delete_tag('default.orders', 'daily-2025-03-27');

Time Travel: чтение исторического состояния

Time travel в Paimon работает через snapshot ID или tag:

Time Travel: три способа доступа к историческим данным
По Snapshot IDПрямой доступ по номеру snapshot: SELECT * FROM orders VERSION AS OF 720. Paimon открывает metadata snapshot-720 и читает referenced data files. Работает только если snapshot ещё не expire'd.
По TagДоступ по имени тега: SELECT * FROM orders VERSION AS OF 'daily-2025-03-27'. Tag разрешается в snapshot ID. Работает всегда, пока тег существует — независимо от snapshot retention.
По TimestampДоступ по времени: SELECT * FROM orders TIMESTAMP AS OF TIMESTAMP '2025-03-27 12:00:00'. Paimon находит ближайший snapshot ≤ указанного времени. Работает в рамках retention window.

Сравнение с другими форматами:

Time Travel: Paimon vs Delta Lake vs Iceberg vs Hudi
Delta LakeTime travel по version number или timestamp. VACUUM удаляет файлы старше retention (по умолчанию 7 дней). После VACUUM — time travel невозможен. Нет аналога tag — нельзя защитить конкретную версию от VACUUM.
Apache IcebergTime travel по snapshot ID или timestamp. expire_snapshots удаляет metadata. Tag (branch) — аналог Paimon tag: именованный snapshot, защищённый от expire. WAP (Write-Audit-Publish) через branches.
Apache HudiTime travel через timeline instants (commit timestamp). Archived timeline (LSM-формат в Hudi 1.0) хранит историю бессрочно. Savepoints — аналог tag: защищённые instants. Incremental query по диапазону instants.
Apache PaimonTime travel по snapshot ID, tag или timestamp. Auto-tag по расписанию — уникальная возможность: ежедневные/еженедельные tag'и автоматически. tag.num-retained-max ограничивает количество. Snapshot expire + tag retention = гибкий lifecycle.

Snapshot Lifecycle: полная картина

Snapshot Lifecycle: от создания до garbage collection
  1. Commit → Snapshot
1. Commit: write или compaction создаёт новый snapshot. Snapshot содержит: список manifest'ов → список data файлов → statistics. Metadata записывается в snapshot-N файл.
  1. Active Window Retention: N snapshot’ов
2. Active Window: snapshot доступен для чтения, time travel, streaming read. Количество активных snapshot'ов = num-retained-max. Streaming reader может подписаться на changelog между snapshot'ами.
  1. Expire Metadata удалена
3. Expire: snapshot metadata удаляется. Data файлы, referenced только этим snapshot, становятся orphan candidates. Если data файл referenced другим snapshot или тегом — он остаётся.
  1. GC: orphan files Storage освобождён
4. GC: orphan files (data + metadata), не referenced никакими snapshot'ами или тегами, удаляются. Освобождается storage. Запускается отдельной процедурой или автоматически.
Tag: пересекает lifecycleTag создаёт persistent ссылку на snapshot. Когда snapshot expire'd — tag сохраняет доступ к data файлам. GC не удаляет файлы, referenced тегом. Tag с retention: tag.num-retained-max = 30 → старые теги удаляются, их файлы становятся orphan candidates.

Подводим итоги

Data management в Paimon — это баланс между write performance (минимальная компакция), read performance (максимальный data skipping) и storage cost (snapshot lifecycle + GC):

  1. Компакция — настраивайте trigger threshold под workload: стриминг (частая, мелкая) vs batch (редкая, крупная). Universal compaction для read-heavy, sorted-run для write-heavy.

  2. Deletion vectors — для append-only таблиц: DELETE без перезаписи файлов. Roaring bitmap, O(1) check per row. Периодическая компакция merge’ит DV в data files.

  3. Z-order — для аналитических запросов по нескольким колонкам. Дорогая одноразовая перезапись, но кардинальное улучшение data skipping.

  4. Data skipping — многоуровневый: partition → bucket → min/max → bloom filter → row group. Bloom filter для high-cardinality equality, z-order для multi-column ranges.

  5. Snapshot lifecycle — expire по count или time, tag для protection, auto-tag для расписания. GC для orphan files.

В следующем уроке мы рассмотрим экосистему Paimon: интеграции с Flink, Spark, OLAP-движками, Iceberg compatibility layer и сравнение с Hudi, Delta Lake и Iceberg.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Paimon streaming-таблица: 10 sorted runs в бакете, num-sorted-run.compaction-trigger = 5. Компакция не запускалась. Каков текущий read overhead и что произойдёт при запуске компакции?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 6