Шифрование, Schema Evolution, сравнение с Parquet
Column Encryption
Начиная с Apache ORC 1.6, формат поддерживает column-level encryption — шифрование отдельных колонок без шифрования всего файла. Это позволяет разным пользователям видеть разные колонки в зависимости от их ключей доступа.
KMS (Key Management Service)
Key Management Service (KMS) — внешний сервис, хранящий master keys. ORC writer запрашивает у KMS ключи шифрования перед записью. Hadoop KMS, AWS KMS, Azure Key Vault.Алгоритм шифрования
ORC использует AES/CTR (Counter Mode) для шифрования данных:
Что шифруется
Что НЕ шифруется
Порядок операций: compress → encrypt. Данные сначала сжимаются (ZSTD, ZLIB, etc.), затем шифрованный блок записывается в файл. При чтении — обратный порядок: decrypt → decompress. AES/CTR поддерживает два размера ключа: 128-bit и 256-bit.
Masked Data
Без доступа к ключу ридер видит зашифрованные колонки как masked data — специальные значения вместо реальных:
| Тип данных | Masked значение | Поведение |
|---|---|---|
| STRING | null или redacted | Ридер возвращает null |
| INT/BIGINT | null | Числовые колонки — null |
| Statistics | Зашифрованы | Min/max/count недоступны |
| Bloom filters | Зашифрованы | Predicate pushdown невозможен |
Schema Evolution
ORC поддерживает ограниченную schema evolution — изменение схемы без перезаписи данных:
ORC имеет два режима schema matching: positional (по умолчанию) и name-based (orc.force.positional.evolution=false). Positional безопаснее для добавления колонок в конец, но не поддерживает переупорядочивание. Name-based гибче, но уязвим к переименованиям. Выбор режима — одноразовое архитектурное решение.
Архитектура компрессии
ORC сжимает данные на уровне chunks (блоков) внутри streams. Каждый блок имеет 3-байтовый заголовок:
Формат 3-байтового заголовка:
byte 0: [is_original:1][length_low:7]
byte 1: [length_mid:8]
byte 2: [length_high:8]
is_original = 0 → данные сжаты кодеком из PostScript
is_original = 1 → данные не сжаты (компрессия неэффективна)
length = (byte2 << 15) | (byte1 << 7) | (byte0 >> 1)
| Кодек | Описание | Типичное применение |
|---|---|---|
| NONE | Без компрессии | Уже сжатые данные, тесты |
| ZLIB | Deflate (gzip-совместим) | Универсальный, хороший ratio |
| SNAPPY | LZ77-based, быстрый | Скорость > ratio |
| LZO | Lempel-Ziv-Oberhumer | Legacy, требует лицензию |
| LZ4 | Очень быстрый, moderate ratio | Real-time pipelines |
| ZSTD | Zstandard | Лучший ratio при хорошей скорости |
По умолчанию ORC использует ZLIB (дефолт ORC library) или SNAPPY (дефолт в некоторых Hive конфигурациях). Для новых проектов рекомендуется ZSTD — лучшее соотношение compression ratio / скорость.
ORC vs Parquet: детальное сравнение
ORC
Parquet
Сводная таблица
| Характеристика | ORC | Parquet |
|---|---|---|
| Организация | Apache (бывш. Hive sub-project) | Apache (бывш. Twitter/Cloudera) |
| Magic number | ORC (3 байта) | PAR1 (4 байта) |
| Сериализация метаданных | Protocol Buffers | Apache Thrift |
| Horizontal split | Stripe (64–250 MB) | Row Group (~128 MB) |
| Компрессия метаданных | Footer сжат | Footer не сжат |
| Bootstrap | PostScript (не сжат) | Footer length (4 bytes LE) |
| Index stride | 10 000 строк (default) | Per-page (Data Page V2) |
| Bloom filters | Встроенные (murmur3 + wang) | Опциональные (murmur3) |
| Integer encoding | RLEv2 (Short Repeat, Direct, Patched Base, Delta) | RLE_DICTIONARY, DELTA_BINARY_PACKED |
| String encoding | Dictionary (sorted) + RLEv2 | RLE_DICTIONARY + PLAIN fallback |
| Float encoding | IEEE 754 прямая запись | BYTE_STREAM_SPLIT (split по байтам) |
| Nested types | STRUCT, LIST, MAP, UNION | group, repeated, map (logical) |
| Column encryption | AES/CTR, per-column (since ORC 1.6) | AES/GCM + AES/CTR (Parquet-MR) |
| Schema evolution | Positional + name-based | Name-based (по умолчанию) |
| ACID транзакции | Hive ACID (native) | Delta Lake / Iceberg / Hudi |
| Экосистема | Hive, Spark, Presto/Trino, Flink | Spark, DuckDB, Polars, Arrow, Pandas |
| Python API | pyarrow.orc (базовая) | pyarrow.parquet (полная) |
В реальных проектах выбор между ORC и Parquet часто определяется экосистемой, а не техническими характеристиками формата. Hive-центричные pipeline используют ORC. Spark/Arrow/DuckDB-центричные — Parquet. Оба формата production-ready и решают одну задачу — эффективное колоночное хранение.
Когда выбирать ORC
Нужен ACID без Delta Lake / Iceberg?
Первый вопрос: нужны ли вам UPDATE/DELETE без внешнего table format (Delta Lake, Iceberg)?→ ORC (Hive ACID)
Если нужен ACID и используется Hive — ORC единственный вариант. Hive ACID работает ТОЛЬКО с ORC.→ следующий вопрос
Если ACID не нужен или используете Delta Lake/Iceberg — следующий вопрос.Основной движок чтения?
Второй вопрос: основной инструмент чтения данных?Hive / Presto → ORC
Hive, Presto/Trino с Hive connector — ORC оптимизирован для этого стека. Predicate pushdown, bloom filters, vectorized reader.Spark / DuckDB / Polars → Parquet
Spark, DuckDB, Polars, Pandas, Arrow — Parquet имеет лучшую поддержку. Arrow-native формат, zero-copy читатели, широкая экосистема.Ключевые выводы
- Column encryption: AES/CTR, per-column, управление ключами через KMS. Шифруются данные, индексы и статистики — но не PostScript и schema
- Schema evolution: безопасно добавлять колонки в конец и расширять числовые типы. Удаление и переупорядочивание — не поддерживаются
- Компрессия: chunk-level с 3-байтовым заголовком, is_original флаг для несжимаемых блоков. Рекомендуется ZSTD
- ORC vs Parquet: похожие по архитектуре, отличаются экосистемой. ORC — Hive/ACID, Parquet — Arrow/Spark/DuckDB
- Выбор формата определяется инструментами и потребностью в ACID, а не техническим превосходством одного над другим