F3 Architecture
F3 (Future-proof File Format) — исследовательский формат, разработанный CMU Database Group. Авторы: Andrew Pavlo, Jignesh Patel, Wes McKinney (создатель Apache Arrow и Pandas), Huanchen Zhang. Опубликован на SIGMOD 2025 (сентябрь 2025) — одной из двух top-tier конференций по базам данных.
F3 — исследовательский прототип, а не production-ready формат. GitHub: future-file-format/F3 (Rust). Нет PyPI пакета, нет Docker image, нет production deployments. Ценность для инженера — понимание архитектурных идей, которые могут появиться в будущих форматах (включая Parquet 3.0).
F3 назван «Future-proof» потому что решает фундаментальную проблему: как обновлять кодировки данных без обновления библиотек на всех серверах. Текущие форматы (Parquet, ORC) требуют, чтобы reader знал все кодировки файла. Неизвестная кодировка = ошибка чтения. F3 решает это через embedded WebAssembly decoders (подробнее в уроке 04).
F3 является частью broader research программы CMU по форматам хранения: «An Empirical Evaluation of Columnar Storage Formats» (VLDB 2023), «NULLS!» (DaMoN 2024), «Towards Functional Decomposition of Storage Formats» (CIDR 2025). Wes McKinney, один из авторов F3, — создатель Apache Arrow и Pandas.
Три принципа F3
F3 строится на трёх принципах, каждый из которых — ответ на конкретное ограничение Parquet:
Interoperability
Interoperability: любой reader с Wasm runtime может прочитать любой F3 файл, даже с custom encodings. Нет зависимости от конкретной библиотеки. Contrast: Nimble (один reader), Parquet (reader должен знать все encodings).Extensibility
Extensibility: новые кодировки deploy'ятся мгновенно — embed Wasm decoder в файл. Нет необходимости обновлять reader libraries на тысячах серверов. Writer решает, какую кодировку использовать.Efficiency
Efficiency: несмотря на Wasm overhead (10-30% vs native), F3 компенсирует за счёт storage layout improvements: IOUnit tuning, decoupled dictionaries, column-level I/O skip.Структура файла F3
F3 вводит два ключевых понятия: IOUnit (единица I/O) и EncUnit (единица кодирования). В Parquet оба привязаны к row group/page — F3 развязывает их:
IOUnit: развязка I/O и логики
Ключевая инновация F3 — IOUnit decoupled from row group. В Parquet размер I/O определяется row group (обычно ~128MB). F3 позволяет writer’у настраивать размер I/O-единицы независимо:
Parquet: I/O = Row Group
Parquet: I/O unit = row group или column chunk. Размер фиксирован writer'ом при создании файла. Обычно ~128MB. Оптимально для HDFS (block size 128MB), но не для NVMe или S3.F3: IOUnit (tunable)
F3: IOUnit = отдельная абстракция. Writer настраивает размер под target storage. Один и тот же logical row group может быть разбит на IOUnits разного размера для разных storage media.IOUnit decoupling — практически значимая идея. Современные storage системы: NVMe SSD (4KB pages, 4MB optimal reads), cloud object storage (S3 с optimal 8-64MB GET requests), persistent memory (64B cache lines). Один формат файла должен работать эффективно на всех. Parquet’s fixed row group = compromise. F3’s tunable IOUnit = per-medium optimization.
EncUnit: минимальная единица кодирования
Внутри IOUnit данные организованы в EncUnits — минимальные единицы кодирования/декодирования:
IOUnit
IOUnit содержит EncUnits для одной или нескольких колонок. Каждый EncUnit — самодостаточная единица: содержит encoded данные + ссылку на Wasm decoder. Можно декодировать один EncUnit без остальных.В Parquet аналог EncUnit — page (data page внутри column chunk). Но page в Parquet привязана к column chunk, который привязан к row group. F3 развязывает эту иерархию:
Decoupled Dictionary Scope
В Parquet dictionary привязан к column chunk (= row group). Это создаёт проблему для высококардинальных колонок:
Parquet: Dict = Row Group scope
Parquet: dictionary = один на column chunk (= row group). Если row group = 1M строк, dictionary содержит все уникальные значения для 1M строк. High cardinality (100K уникальных) → dictionary > value column → fallback на PLAIN.F3: Dict = Configurable scope
F3: dictionary scope = configurable. Writer выбирает: per-EncUnit (узкий), per-IOUnit, per-row-group, per-file (широкий). Оптимальный scope зависит от кардинальности и query patterns.FlatBuffer Metadata с Column-Level I/O Skip
F3 использует FlatBuffers (как Nimble и Vortex) для метаданных с дополнительной оптимизацией — column-level I/O skip:
Column-level I/O skip — не уникальная идея F3. Parquet тоже может пропускать колонки (column projection). Разница в metadata efficiency: Parquet footer содержит Thrift для ВСЕХ колонок (нужно десериализовать всё), F3 footer — FlatBuffers с per-column offsets (читаем только нужные). При 1000+ колонок разница ощутима.
General-Purpose Decoding API
F3 определяет стандартный API, который должен реализовать каждый Wasm decoder:
Сравнение с Parquet Page Structure
Parquet Hierarchy
Parquet: жёсткая иерархия. File → Row Groups → Column Chunks → Pages. Каждый уровень привязан к предыдущему. Row group определяет scope dictionary, column chunk определяет scope pages.F3 Hierarchy
F3: развязанная иерархия. Logical Row Group (строки), IOUnit (bytes, physical), EncUnit (encoding). Три независимые размерности: сколько строк, сколько bytes per I/O, какой encoding scope.Развязка позволяет оптимизировать каждую размерность независимо:
Wasm Decoder Registry
Footer F3 файла содержит registry embedded Wasm decoders:
Wasm modules дедуплицируются: один файл с 100 integer колонками ссылается на один delta-varint decoder (5KB), а не 100 копий. Registry overhead: количество уникальных encodings × средний module size. Для типичного файла (3-5 encodings): 15-100KB — меньше одного Parquet page.
Полный Read Path
Как F3 reader обрабатывает запрос:
Decoded Columns → Apply Filter → Result
Decoded column data: col_A values, col_B values (для filter), col_C values. Стандартный columnar output — Arrow-compatible. Filter: apply col_B > 100 на decoded values.Сравнение с форматами курса
Итоги
F3 — это архитектурный blueprint, а не production формат. Ключевые инновации:
-
Decoupled hierarchy. Три независимые размерности: logical (row group), physical (IOUnit), encoding (EncUnit). В Parquet все три связаны через row group.
-
Tunable IOUnit. Writer настраивает I/O unit size под storage medium: 4MB для NVMe, 64MB для S3. Нет компромиссов.
-
Decoupled dictionary scope. Dictionary scope — независимый параметр, не привязан к row group. Оптимальный выбор per column cardinality.
-
FlatBuffer metadata с column-level skip. Reader deseriализует metadata только нужных колонок — O(K) вместо O(N) для K из N колонок.
-
Embedded Wasm decoders. Каждый файл самодостаточен — содержит decoder’ы для своих данных. Подробнее в следующем уроке.
Следующий урок — F3 Wasm-декодеры: как именно работает embedded Wasm, какой overhead, и как это решает проблему fleet-wide encoding deployment.