Learning Platform
Глоссарий Troubleshooting
Урок 04.05 · 30 мин
Продвинутый
ORCACIDHiveCompactionDelta FilesTransaction VisibilityRow ID

ACID-транзакции

ORC — immutable, ACID — Hive

Важнейшая архитектурная граница: ORC сам по себе — immutable формат. Файл ORC нельзя обновить на месте — он записывается один раз и только читается. Всё, что называется “ACID в ORC” — это Hive-уровневая абстракция, использующая ORC как storage substrate.

Hive ACID реализует INSERT, UPDATE, DELETE поверх immutable ORC-файлов через паттерн base + delta: исходные данные живут в base-файле, а изменения записываются в отдельные delta-директории. Чтение объединяет base и дельты через merge sort.

ACID — уровни абстракции

Что умеет ORC (формат)

Immutable файлы

ORC — write-once формат. Файл создаётся целиком и дальше только читается. Нет in-place update, нет append к существующему файлу.

Колоночное хранение

Колоночное хранение с компрессией, индексами, bloom filters, column statistics. Оптимизирован для чтения.

Индексы и статистики

Row index с min/max/count по каждые 10 000 строк. Bloom filters для point lookups. SARGs для predicate pushdown.

Что добавляет Hive (runtime)

Base + Delta файлы

Hive записывает INSERT/UPDATE/DELETE как отдельные дельта-файлы рядом с base. Это уровень файловой системы (HDFS), не формата ORC.

Row ID (скрытые колонки)

Каждая строка получает уникальный (originalTransaction, bucket, rowId) — row ID. Записывается как скрытые колонки в ORC-файл.

Compaction (minor / major)

Minor compaction: объединяет дельты. Major compaction: объединяет base + все дельты в новый base. Фоновые процессы Hive Metastore.

Transaction Manager

Менеджер транзакций в Hive Metastore: write IDs, valid transaction list, isolation levels.
WARNING

ORC — это формат хранения. ACID — это runtime-слой Hive. Если вы читаете ORC-файл напрямую через PyArrow или DuckDB, вы получаете raw данные без транзакционной семантики. Дельты, compaction и transaction visibility — ответственность Hive.

Структура директорий: base + delta

Hive ACID-таблица хранится на HDFS как набор директорий. Каждая транзакция создаёт новую delta-директорию:

Файловая структура ACID-таблицы
warehouse/db.db/transactions_table/Корневая директория ACID-таблицы в Hive warehouse. Может быть партиционирована — тогда base/delta лежат внутри директории партиции.
ДиректорияСодержимоеКогда создаётся
base_NNNNNNN/Полный snapshot данныхInitial load или major compaction
delta_MIN_MAX/Вставленные строкиINSERT, UPDATE (новая версия строки)
delete_delta_MIN_MAX/Row IDs удалённых строкDELETE, UPDATE (удаление старой версии)
NOTE

UPDATE в Hive ACID — это split operation: delete старой версии строки (запись в delete_delta) + insert новой версии (запись в delta). Поэтому одна UPDATE-операция создаёт две директории.

Row ID: уникальный идентификатор строки

Каждая строка в ACID-таблице имеет уникальный Row ID — составной ключ из трёх компонентов:

Структура Row ID
originalTransaction (writeId)ID транзакции, которая первоначально записала эту строку. При INSERT — ID текущей транзакции. При UPDATE — ID транзакции, создавшей новую версию.
bucket (int32)Номер bucket (0-based). В ACID-таблице данные распределяются по bucket файлам. Bucket определяется хеш-функцией от clustering columns.
rowId (int64)Порядковый номер строки внутри bucket для данной транзакции. Начинается с 0 для каждой пары (writeId, bucket).

Row ID хранится как скрытые колонки в ORC-файле. Когда Hive записывает дельту, каждая строка содержит три служебных поля перед пользовательскими данными:

// Структура записи в ACID delta-файле
struct AcidRow {
 operation: int // 0=INSERT, 1=UPDATE, 2=DELETE
 originalTransaction: bigint // writeId создавшей транзакции
 bucket: int // номер bucket
 rowId: bigint // номер строки в bucket
 currentTransaction: bigint // writeId текущей транзакции
 // ... пользовательские колонки ...
}
TIP

Тройка (originalTransaction, bucket, rowId) — глобально уникальный идентификатор строки. Delete-дельта содержит только эти три поля — без пользовательских данных. При чтении ридер использует row ID для merge sort: находит строку в base/delta и проверяет, не удалена ли она в delete_delta.

Merge Sort при чтении

Чтение ACID-таблицы — это merge sort base и всех дельт:

Merge Sort при чтении ACID-таблицы
base_0000005Полный snapshot. Строки отсортированы по row ID. Ридер открывает sorted stream.
delta_0000006INSERT-дельта. Новые строки тоже имеют row ID. Ридер открывает второй sorted stream.
delete_delta_0000008Список row ID удалённых строк. Ридер использует как фильтр: если row ID строки из base/delta совпадает с записью в delete_delta — строка пропускается.

Merge Sort по Row ID

ORC Reader выполняет merge sort по row ID. Все streams (base + deltas) отсортированы — merge эффективен. Delete delta работает как negative filter.

Фильтрация удалённых + выбор последней версии

Для каждого row ID: проверить, нет ли его в delete_delta (удалён?). Если есть — пропустить. Если row ID встречается в нескольких delta — взять версию с максимальным writeId.

Результирующий набор строк

Результат: консистентный snapshot таблицы с учётом всех INSERT, UPDATE, DELETE. Пользователь видит обычную таблицу.

Алгоритм:

  1. Открыть base-файл и все delta-файлы как отсортированные потоки по row ID
  2. Merge sort всех потоков — строки приходят в порядке row ID
  3. Для каждого row ID: проверить delete_delta — если row ID удалён, пропустить
  4. Если несколько дельт содержат одинаковый row ID — взять версию с максимальным currentTransaction
  5. Выдать результирующую строку

Compaction: объединение файлов

Со временем накапливаются десятки дельт — чтение замедляется. Compaction — фоновый процесс Hive Metastore, который объединяет файлы:

Minor и Major Compaction

Minor Compaction

delta_6_6Входная дельта. Minor compaction не трогает base — только объединяет дельты между собой.
delta_7_7Ещё одна входная дельта.
delta_8_8И третья.

Minor compaction

Minor compaction: merge дельт без перезаписи base. Быстрая операция — не перечитывает основные данные. Результат: одна объединённая delta-директория.
delta_6_8Объединённая дельта: содержит все изменения транзакций 6–8. Три старые delta-директории удаляются.

Быстрая: не трогает base
Base по-прежнему отдельно

Major Compaction

base_5Текущий base. Major compaction перечитывает все данные — base + все дельты.
delta_6_8Объединённая (или несколько) дельт.

Major compaction

Major compaction: полный merge base + все delta + delete_delta. Применяет DELETE, разрешает UPDATE. Результат — новый чистый base без дельт.
base_0000008Новый base с ID последней транзакции. Содержит полный snapshot с учётом всех изменений. Все старые base/delta/delete_delta удаляются.

Чистый snapshot, быстрое чтение
Дорогая: перезапись всех данных

ХарактеристикаMinor CompactionMajor Compaction
Что объединяетДельты между собойBase + все дельты
Трогает base (перезаписывает)
Delete-дельтыСохраняютсяПрименяются и удаляются
СкоростьБыстраяМедленная (полная перезапись)
РезультатМеньше дельтОдин чистый base
Когда нужнаНакопилось много мелких дельтНакопилось много delete_delta

Transaction Visibility

Hive Metastore поддерживает Valid Transaction List — список завершённых (committed) транзакций. При чтении таблицы:

Транзакционная видимость
Запрос Valid Transaction List у MetastoreШаг 1: Ридер запрашивает у Hive Metastore текущий snapshot — список committed транзакций и high water mark (максимальный writeId).
Фильтрация дельт по Valid Transaction ListШаг 2: Сканирование директорий. Ридер включает только delta/delete_delta с writeId, присутствующим в valid list. Uncommitted или aborted транзакции — игнорируются.

Merge sort видимых base + delta

Шаг 3: Merge sort отфильтрованных потоков. Snapshot isolation: каждый читатель видит консистентное состояние на момент начала запроса.

Snapshot Isolation (консистентный результат)

Результат: snapshot isolation. Параллельные записи не видны текущему читателю. ACID гарантии обеспечиваются Hive Metastore + HDFS, не форматом ORC.
WARNING

Snapshot isolation в Hive ACID работает на уровне всей таблицы, не на уровне строк. Каждый запрос видит один snapshot. Конфликты записей (write-write) разрешаются через lock manager в Metastore — первая committed транзакция побеждает, конкурирующая — abort.

Ограничения Hive ACID

Hive ACID решает задачу UPDATE/DELETE на immutable storage, но имеет существенные ограничения:

Ограничения Hive ACID
Read AmplificationПри 100 дельтах ридеру нужно открыть и merge sort 101 файл (base + 100 дельт). Каждый дополнительный delta — overhead на чтение.
Только ORCHive ACID работает ТОЛЬКО с ORC-форматом. Parquet, Avro, CSV — не поддерживаются для ACID-таблиц. Это архитектурное ограничение: row ID кодируется как ORC-колонки.
Compaction overheadMajor compaction перезаписывает все данные. Для таблицы 1 TB — это 1 TB I/O. Требует мониторинга и планирования.
Не поддерживает MVCCНет полноценного MVCC с версионированием строк. Time travel ограничен — нельзя прочитать состояние таблицы на произвольный момент в прошлом (в отличие от Delta Lake/Iceberg).

Hive ACID vs Delta Lake / Iceberg

Hive ACID — первая реализация ACID на immutable columnar storage. Современные форматы (Delta Lake, Apache Iceberg) развивают эту идею:

ХарактеристикаHive ACIDDelta LakeApache Iceberg
Storage форматТолько ORCТолько ParquetParquet, ORC, Avro
Метаданные транзакцийHive Metastore_delta_log/ (JSON/Parquet)metadata/ (Avro/JSON)
Time travel (version/timestamp) (snapshot ID/timestamp)
Schema evolutionОграниченная (полная)
CompactionФоновый (Metastore)OPTIMIZERewrite data files
IsolationSnapshot (Metastore locks)Optimistic concurrencyOptimistic concurrency

Ключевые выводы

  1. ORC — immutable формат. ACID — это Hive-уровневый runtime, использующий ORC как storage substrate
  2. Base + Delta паттерн: base-файл — snapshot, delta — вставки, delete_delta — удаления. UPDATE = delete + insert
  3. Row ID (originalTransaction, bucket, rowId) — глобально уникальный идентификатор строки, хранится как скрытые ORC-колонки
  4. Merge sort при чтении: все потоки объединяются по row ID, delete_delta фильтрует удалённые строки
  5. Compaction: minor (дельты → одна дельта) и major (base + дельты → новый base)
  6. Transaction visibility: через Valid Transaction List из Hive Metastore, snapshot isolation
Spark: lakehouse и эволюция от Hive ACID

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

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. Hive ACID выполняет UPDATE на ORC-таблицу: UPDATE orders SET status='shipped' WHERE id=100. Что физически происходит на HDFS?

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

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

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

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