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.
Что умеет 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.ORC — это формат хранения. ACID — это runtime-слой Hive. Если вы читаете ORC-файл напрямую через PyArrow или DuckDB, вы получаете raw данные без транзакционной семантики. Дельты, compaction и transaction visibility — ответственность Hive.
Структура директорий: base + delta
Hive ACID-таблица хранится на HDFS как набор директорий. Каждая транзакция создаёт новую delta-директорию:
| Директория | Содержимое | Когда создаётся |
|---|---|---|
base_NNNNNNN/ | Полный snapshot данных | Initial load или major compaction |
delta_MIN_MAX/ | Вставленные строки | INSERT, UPDATE (новая версия строки) |
delete_delta_MIN_MAX/ | Row IDs удалённых строк | DELETE, UPDATE (удаление старой версии) |
UPDATE в Hive ACID — это split operation: delete старой версии строки (запись в delete_delta) + insert новой версии (запись в delta). Поэтому одна UPDATE-операция создаёт две директории.
Row ID: уникальный идентификатор строки
Каждая строка в ACID-таблице имеет уникальный Row ID — составной ключ из трёх компонентов:
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 текущей транзакции
// ... пользовательские колонки ...
}
Тройка (originalTransaction, bucket, rowId) — глобально уникальный идентификатор строки. Delete-дельта содержит только эти три поля — без пользовательских данных. При чтении ридер использует row ID для merge sort: находит строку в base/delta и проверяет, не удалена ли она в delete_delta.
Merge Sort при чтении
Чтение ACID-таблицы — это merge sort base и всех дельт:
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. Пользователь видит обычную таблицу.Алгоритм:
- Открыть base-файл и все delta-файлы как отсортированные потоки по row ID
- Merge sort всех потоков — строки приходят в порядке row ID
- Для каждого row ID: проверить delete_delta — если row ID удалён, пропустить
- Если несколько дельт содержат одинаковый row ID — взять версию с максимальным
currentTransaction - Выдать результирующую строку
Compaction: объединение файлов
Со временем накапливаются десятки дельт — чтение замедляется. Compaction — фоновый процесс Hive Metastore, который объединяет файлы:
Minor Compaction
Minor compaction
Minor compaction: merge дельт без перезаписи base. Быстрая операция — не перечитывает основные данные. Результат: одна объединённая delta-директория. Быстрая: не трогает base
Base по-прежнему отдельно
Major Compaction
Major compaction
Major compaction: полный merge base + все delta + delete_delta. Применяет DELETE, разрешает UPDATE. Результат — новый чистый base без дельт. Чистый snapshot, быстрое чтение
Дорогая: перезапись всех данных
| Характеристика | Minor Compaction | Major Compaction |
|---|---|---|
| Что объединяет | Дельты между собой | Base + все дельты |
| Трогает base | (перезаписывает) | |
| Delete-дельты | Сохраняются | Применяются и удаляются |
| Скорость | Быстрая | Медленная (полная перезапись) |
| Результат | Меньше дельт | Один чистый base |
| Когда нужна | Накопилось много мелких дельт | Накопилось много delete_delta |
Transaction Visibility
Hive Metastore поддерживает Valid Transaction List — список завершённых (committed) транзакций. При чтении таблицы:
Merge sort видимых base + delta
Шаг 3: Merge sort отфильтрованных потоков. Snapshot isolation: каждый читатель видит консистентное состояние на момент начала запроса.Snapshot Isolation (консистентный результат)
Результат: snapshot isolation. Параллельные записи не видны текущему читателю. ACID гарантии обеспечиваются Hive Metastore + HDFS, не форматом ORC.Snapshot isolation в Hive ACID работает на уровне всей таблицы, не на уровне строк. Каждый запрос видит один snapshot. Конфликты записей (write-write) разрешаются через lock manager в Metastore — первая committed транзакция побеждает, конкурирующая — abort.
Ограничения Hive ACID
Hive ACID решает задачу UPDATE/DELETE на immutable storage, но имеет существенные ограничения:
Hive ACID vs Delta Lake / Iceberg
Hive ACID — первая реализация ACID на immutable columnar storage. Современные форматы (Delta Lake, Apache Iceberg) развивают эту идею:
| Характеристика | Hive ACID | Delta Lake | Apache Iceberg |
|---|---|---|---|
| Storage формат | Только ORC | Только Parquet | Parquet, ORC, Avro |
| Метаданные транзакций | Hive Metastore | _delta_log/ (JSON/Parquet) | metadata/ (Avro/JSON) |
| Time travel | (version/timestamp) | (snapshot ID/timestamp) | |
| Schema evolution | Ограниченная | (полная) | |
| Compaction | Фоновый (Metastore) | OPTIMIZE | Rewrite data files |
| Isolation | Snapshot (Metastore locks) | Optimistic concurrency | Optimistic concurrency |
Ключевые выводы
- ORC — immutable формат. ACID — это Hive-уровневый runtime, использующий ORC как storage substrate
- Base + Delta паттерн: base-файл — snapshot, delta — вставки, delete_delta — удаления. UPDATE = delete + insert
- Row ID
(originalTransaction, bucket, rowId)— глобально уникальный идентификатор строки, хранится как скрытые ORC-колонки - Merge sort при чтении: все потоки объединяются по row ID, delete_delta фильтрует удалённые строки
- Compaction: minor (дельты → одна дельта) и major (base + дельты → новый base)
- Transaction visibility: через Valid Transaction List из Hive Metastore, snapshot isolation