Найти в Дзене
Цифровая Переплавка

🗄 Проблема equality delete в Apache Iceberg: как CDC ломает идеальную картину

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

Интеграция PostgreSQL и Apache Iceberg стала стратегическим направлением для гигантов вроде Snowflake и Databricks. Постгрес — для транзакционных операций, Iceberg — для масштабной аналитики. Но как только речь заходит о потоковом CDC (Change Data Capture), возникает тихая, но болезненная проблема: как удалять данные?

🔍 Два пути удаления в Iceberg

В Iceberg предусмотрены два механизма row-level delete:

  • 📍 Position delete — удаление по физическому адресу (путь файла + номер строки).
    ✅ Отличная производительность чтения — движок просто пропускает строки.
    ❌ Требует заранее знать физическое расположение строки, что для стриминга почти нереально.
  • 🗝 Equality delete — удаление по значению столбцов (обычно по первичному ключу).
    ✅ Записываем только ключ — идеально для CDC.
    ❌ Чтение превращается в merge-on-read, а количество delete-файлов растёт → нужна регулярная компакция.

⚙ Почему equality delete — единственный вариант для CDC

В потоковом сценарии мы не знаем, в каком файле и на какой строке лежит удаляемая запись. CDC из Postgres через Debezium или Flink отдаёт нам только ключ и старое/новое значение.

💡 В итоге для CDC остаётся только equality delete, иначе придётся каждый раз сканировать Iceberg в поисках позиции строки, что убьёт латентность и пропускную способность.

🚧 Проблема совместимости

Поддержка equality delete в популярных движках выглядит печально:

  • Snowflake: во внешних Iceberg-таблицах — только position delete.
  • 🔥 Databricks: нет поддержки ни одного типа row-level delete.
  • 🟥 Redshift: equality delete поддерживается (Iceberg v2, внешний каталог).

Итог — в большинстве экосистем CDC с equality delete просто не будет корректно читаться.

🛠 Инженерный взгляд: стратегия RisingWave

RisingWave предложил гибридный подход, чтобы CDC → Iceberg реально работал в продакшене:

  • 🔄 На записи:
    Если в одном батче ключ обновлялся несколько раз — применяем position delete (уже знаем физическую позицию).
    Если ключ вне батча — используем equality delete.
  • 🧹 Компакция:
    Планировщик удаляет накопившиеся equality delete и сливает мелкие файлы.
    Режимы:
    🏎 Low-latency — компакция каждые ~минуту.
    💤 Offline — реже, чтобы снизить нагрузку на S3 и стоимость API-вызовов.
  • 🔗 Экспорт для несовместимых движков:
    Перед экспортом делаем таргетную компакцию, чтобы отдать «чистую» версию без equality delete.
    Внутренние сервисы продолжают читать «грязную» версию с минимальной задержкой.
  • 🛡 Гарантии exactly-once и идемпотентности:
    Все коммиты повторяемы и проверяемы, что убирает дубликаты и потери данных.

📊 Реальный кейс: Siemens

До RisingWave:

  • CDC → Iceberg с equality delete.
  • Snowflake не мог читать эти удаления.
  • Приходилось запускать Spark для полной очистки delete-файлов → задержки и рост стоимости.

После:

  • Гибридная стратегия delete.
  • Автокомпакция.
  • Snowflake читает «чистую» версию без Spark.
  • Задержка упала с батч-уровня до real-time.

💭 Мой вывод

Equality delete — это не баг, а цена стриминга. Мы переносим сложность с записи (где важна низкая задержка) на чтение (где можно оптимизировать асинхронно). Но без продуманной стратегии компакции и совместимости это превращается в ловушку для инженеров.

RisingWave показал, что грамотное сочетание position + equality, плюс планомерная компакция и экспорт могут сделать CDC → Iceberg жизнеспособным даже в условиях несовершенной поддержки движков.

🔗 Источник: The Equality Delete Problem in Apache Iceberg