Learning Platform
Глоссарий Troubleshooting
Урок 04.01 · 25 мин
Средний
ORCStripesFile StructurePostScriptFooterProtocol Buffers

Stripes и физическая структура

Структура ORC-файла

ORC (Optimized Row Columnar) — колоночный формат, созданный в экосистеме Hive. Физическая структура отличается от Parquet: магическая сигнатура короче, метаданные сериализованы через Protocol Buffers (не Thrift), а чтение файла начинается с последнего байта — PostScript.

Файл начинается с 3-байтовой сигнатуры ORC (hex: 4F 52 43). Обратите внимание — это 3 байта, а не 4 как PAR1 у Parquet. После сигнатуры идут stripes с данными, а в конце — Footer, Metadata и PostScript.

Физическая структура ORC-файла
ORC (3 байта — magic number)3 байта: 0x4F 0x52 0x43. Magic number для идентификации формата. Короче PAR1 (4 байта) у Parquet.
Stripe 0Первая stripe — основная единица данных. Содержит index data, row data и stripe footer. Размер по умолчанию 64 MB (ORC lib) или 250 MB (Hive).
Stripe 1Следующая stripe. Каждая stripe независима — содержит свои индексы и данные. Можно читать параллельно.
...Количество stripes зависит от объёма данных и настройки stripe size.

Footer (Protobuf-encoded)

Protobuf-сериализованная структура Footer: схема типов (type tree), stripe information, статистики по колонкам, user metadata.

File Metadata (Protobuf-encoded)

Protobuf-сериализованная структура Metadata: stripe-level статистики (column stats per stripe). Опциональная — может быть пустой.

PostScript (последний элемент файла)

Последний элемент файла. НЕ Protobuf — чистые байты фиксированного формата. Содержит длины Footer и Metadata, версию, кодек компрессии, magic 'ORC'. Размер PostScript — последний байт файла.
TIP

ORC-ридер открывает файл с последнего байта: этот единственный байт содержит длину PostScript. Далее ридер читает PostScript, из него — длины Footer и Metadata, затем подтягивает структуры по offset. Только после этого он знает схему, количество stripes и расположение данных.

Чтение ORC-файла: с конца к началу

Алгоритм чтения — ключевая деталь, которая объясняет, почему метаданные в конце файла:

  1. Читаем последний байт → длина PostScript (1 байт, unsigned)
  2. Читаем PostScript → version, compression, footer length, metadata length, magic
  3. Вычисляем offset Footer = fileSize - 1 - postScriptLength - footerLength
  4. Читаем Footer → schema (type tree), stripe information, file statistics
  5. (Опционально) читаем Metadata → stripe-level column statistics
  6. По stripe information из Footer переходим к нужным stripes
Алгоритм чтения ORC с конца файла

Порядок чтения

① Последний байт → длина PostScript

Шаг 1: читаем ровно 1 байт с конца файла. Значение 0–255 — длина PostScript в байтах.

② PostScript → version, codec, lengths

Шаг 2: читаем PostScript — фиксированная структура без Protobuf. Содержит magic 'ORC', version, compression codec, длины Footer и Metadata.

③ Footer → schema, stripes, statistics

Шаг 3: по длине из PostScript вычисляем offset и декодируем Protobuf-структуру Footer.

④ Seek к нужной stripe → данные

Шаг 4: по stripe offsets из Footer — прямой seek к нужной stripe. Lazy reading — читаем только то, что запрошено.

Сравнение с Parquet

ORC1 байт → PostScript → Footer. PostScript не Protobuf — парсится мгновенно. Два уровня метаданных (Footer + Metadata).
Parquet8 байт (4 length + 4 PAR1) → Footer. Один уровень метаданных (FileMetaData). Thrift-сериализация.

ORC использует промежуточный PostScript для Bootstrap — это позволяет хранить кодек компрессии до чтения Footer (Footer сам может быть сжат)

WARNING

PostScript — единственная структура в ORC-файле, которая никогда не сжимается. Footer и Metadata сжимаются кодеком, указанным в PostScript. Если бы PostScript тоже был сжат, возник бы chicken-and-egg problem: нужно знать кодек, чтобы разжать, но кодек записан в сжатой структуре.

Stripe: основная единица данных

Stripe в ORC аналогична Row Group в Parquet — это горизонтальный срез таблицы, содержащий все колонки для порции строк. Но внутренняя структура stripe более детализирована: каждая stripe содержит три секции.

СекцияСодержимоеНазначение
Index DataRow index streams + bloom filter streamsПредикатное отсечение, seek к row group
Row DataColumn data streams (per-column)Фактические данные колонок
Stripe FooterStream directory + column encodingsКарта потоков внутри stripe
Внутренняя структура Stripe
Stripe (64–250 MB)Одна stripe — самодостаточная единица данных. Содержит свои индексы, данные и метаданные. Параллелизм = количество stripes.

Размер Stripe: настройки

Размер stripe — настраиваемый параметр, влияющий на параллелизм, I/O и использование памяти. Два ключевых значения по умолчанию:

  • ORC library (Java/C++ reference): 64 MB
  • Hive: 250 MB (конфигурация hive.exec.orc.default.stripe.size)
Влияние размера Stripe

Маленькая stripe (16–32 MB)

Маленькие stripes (16–32 MB): больше параллелизма, точнее predicate pushdown, но больше overhead индексов и footer.

Больше параллелизма
Точнее predicate pushdown
Больше index / footer overhead
Больше seek операций

Стандартная stripe (64 MB)

Стандартный размер 64 MB (ORC lib). Баланс между параллелизмом и overhead. Достаточно для HDFS блока (128 MB = 2 stripes).

Хороший баланс
2 stripes на HDFS блок
Достаточная компрессия
Дефолт ORC library

Большая stripe (250 MB)

Большие stripes (250 MB, дефолт Hive): лучшая компрессия, меньше overhead, но грубый параллелизм и большее потребление памяти.

Лучшая компрессия
Меньше overhead
Грубый параллелизм
Больше памяти на чтение

ИнструментПараметрЗначение по умолчанию
ORC Java libraryorc.stripe.size64 MB
Hivehive.exec.orc.default.stripe.size256 MB
Spark (ORC)orc.stripe.size64 MB
Presto / Trinoorc.max-buffer-size8 MB (buffer, не stripe)

PostScript: bootstrap-структура

PostScript — точка входа при чтении файла. Это единственная структура, которая не сжимается и не сериализуется через Protobuf. Она содержит минимум информации, необходимый для начала парсинга:

message PostScript {
 footerLength: uint64 // длина Footer в байтах
 compression: CompressionKind // NONE, ZLIB, SNAPPY, LZO, LZ4, ZSTD
 compressionBlockSize: uint64 // размер блока компрессии (дефолт 256 KB)
 version: [uint32] // [0, 12] для Hive 0.12+
 metadataLength: uint64 // длина File Metadata в байтах
 magic: string // "ORC"
}
NOTE

Поле version — массив из двух элементов: [major, minor]. Версия [0, 11] означает Hive 0.11 (v0 формат с RLEv1). Версия [0, 12] — Hive 0.12+ (v1 формат с RLEv2, индексами и bloom filters). Текущий production-формат — v1 ([0, 12]).

Footer — главная Protobuf-структура файла. Содержит три ключевых блока:

  1. Type tree — схема файла в виде дерева типов (подробнее в уроке 04)
  2. Stripe Information — offset, length, row count для каждой stripe
  3. File Statistics — агрегированные min/max/count по каждой колонке (для всего файла)
message Footer {
 headerLength: uint64
 contentLength: uint64
 types: [Type] // дерево типов
 stripes: [StripeInformation]
 metadata: [UserMetadataItem] // key-value пользовательские метаданные
 numberOfRows: uint64
 statistics: [ColumnStatistics] // per-column stats для всего файла
 rowIndexStride: uint32 // default 10 000
}

Сравнение с Parquet

ХарактеристикаORCParquet
Magic numberORC (3 байта)PAR1 (4 байта)
Сериализация метаданныхProtocol BuffersApache Thrift
Bootstrap-структураPostScript (не сжат) (footer length + PAR1)
Единица горизонтального деленияStripe (64–250 MB)Row Group (128 MB)
Расположение метаданныхPostScript + Footer + MetadataFileMetaData (одна структура)
Компрессия метаданныхFooter и Metadata сжатыFooter не сжат
Количество read-операций для открытия2–3 (PostScript → Footer → Metadata)1–2 (footer length → FileMetaData)

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

  1. ORC-файл начинается с 3-байтовой сигнатуры ORC (hex: 4F 52 43) и читается с конца
  2. PostScript — единственная несжатая структура, содержит кодек компрессии и длины Footer/Metadata
  3. Stripe — основная единица данных (аналог Row Group), содержит Index Data, Row Data и Stripe Footer
  4. Размер stripe по умолчанию: 64 MB (ORC lib) или 250 MB (Hive)
  5. Метаданные сериализованы через Protocol Buffers (Parquet использует Thrift)
  6. Footer содержит type tree, stripe information и file-level statistics
File formats comparison в Spark — практический выбор

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

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. ORC-файл: 1 GB, 8 stripes по ~125 MB. Reader открывает файл. Какой byte offset он читает первым и зачем?

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

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

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

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