Learning Platform
Глоссарий Troubleshooting
Урок 03.01 · 25 мин
Средний
ParquetRow GroupsFile StructureParallel I/OPAR1

Row Groups

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

Parquet-файл — это не просто «колонки на диске». Это строго определённый бинарный формат с магическими байтами, row groups и Thrift-сериализованным футером.

Каждый файл начинается и заканчивается 4-байтовой сигнатурой PAR1 (hex: 50 41 52 31). Между ними — row groups с данными и метаданные в конце файла.

Физическая структура Parquet-файла

PAR1 (4 байта — magic number)

4 байта: 0x50 0x41 0x52 0x31. Magic number для идентификации формата. Без него ридер отклонит файл.
Row Group 0Первая группа строк. Содержит column chunks для каждой колонки. Размер по умолчанию ~128 MB.
Row Group 1Вторая группа строк. Те же колонки, следующая порция строк. Независима от Row Group 0.
...Количество row groups зависит от объёма данных и настройки row_group_size.

File Metadata (Thrift-encoded)

Thrift-сериализованная структура FileMetaData: версия, схема, row groups, key-value metadata, created_by

Metadata Length (4 байта, LE)

4 байта little-endian — длина File Metadata в байтах. Ридер читает последние 8 байт файла: эти 4 + PAR1

PAR1 (4 байта — magic number)

Повторение magic number в конце файла. Позволяет читать файл с конца: PAR1 → length → metadata → data
TIP

Ридер открывает Parquet-файл с конца: читает последние 8 байт (metadata length + PAR1), затем по offset — весь File Metadata. Только после этого он знает схему, количество row groups и расположение каждого column chunk.

Что такое Row Group

Row Group — это горизонтальный срез таблицы. Если файл содержит 10 миллионов строк, а размер row group настроен на 128 MB, файл будет содержать несколько row groups, каждый с частью строк.

Ключевые свойства:

  • Каждый row group содержит все колонки для своей порции строк
  • Внутри row group данные хранятся по колонкам (column chunks)
  • Row group — минимальная единица для параллельного чтения
  • Размер по умолчанию: 128 MB (несжатых данных)
Row Group: горизонтальное партиционирование

Логическая таблица

Строки 0–999 999Первый миллион строк таблицы. Все колонки: id, name, salary, department, ...
Строки 1 000 000–1 999 999Второй миллион строк. Те же колонки, следующая порция данных.
Строки 2 000 000–2 999 999Третий миллион строк. Количество строк в группе зависит от размера данных, не от количества строк.

Parquet row groups

Row Group 0 (~128 MB)Column chunk для id + column chunk для name + ... Все chunks для строк 0–999 999 идут подряд
Row Group 1 (~128 MB)Те же колонки, но для строк 1M–2M. Каждый row group независим — можно читать параллельно.
Row Group 2 (~128 MB)Последний row group может быть меньше 128 MB — содержит оставшиеся строки.

Параллельное чтение

Row groups — это механизм параллелизации. Каждый row group можно читать независимо, потому что он содержит полный набор column chunks для своего диапазона строк.

Spark, Trino, DuckDB распределяют row groups между потоками (или нодами кластера). Больше row groups — больше параллелизма.

Параллельное чтение row groups

Thread 0 → RG 0

Первый поток читает Row Group 0. Доступ к данным последовательный внутри группы — минимум seek операций.
Строки 0–999K

Thread 1 → RG 1

Второй поток читает Row Group 1 одновременно. Никаких блокировок — row groups не пересекаются.
Строки 1M–2M

Thread 2 → RG 2

Третий поток читает Row Group 2. Результаты агрегируются после чтения всех групп.
Строки 2M–3M
NOTE

Один файл с 1 row group → один поток. Десять файлов по 1 row group → десять потоков. Это одна из причин, почему Spark рекомендует размер файлов 128 MB–1 GB — чтобы обеспечить достаточный параллелизм.

Размер Row Group: trade-offs

Размер row group — это настраиваемый параметр, и он влияет на три вещи одновременно:

Влияние размера Row Group

Маленький RG (8–32 MB)

Маленькие row groups (8–32 MB): больше параллелизма, но больше overhead метаданных и хуже компрессия

Больше параллелизма
Точнее row group pruning
Больше metadata overhead
Хуже компрессия

Стандартный RG (128 MB)

Средний row group (128 MB) — баланс между параллелизмом, компрессией и overhead. Дефолт в большинстве движков.

Хороший баланс
Дефолт Spark / PyArrow
Достаточная компрессия
Умеренный overhead

Большой RG (512 MB+)

Большие row groups (512 MB–1 GB): лучшая компрессия, но меньше параллелизма и грубый pruning

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

Настройки размера в разных инструментах:

ИнструментПараметрЗначение по умолчанию
PyArrowrow_group_size64 MB (max_row_group_length)
Sparkparquet.block.size128 MB
DuckDBrow_group_size122 880 строк
Trino (Hive)parquet.writer.block-size128 MB
WARNING

DuckDB задаёт размер row group в строках, а не в байтах. При широких таблицах (сотни колонок) row group из 122 880 строк может оказаться значительно больше 128 MB. Следите за размером файла.

Row Group Pruning

Каждый row group хранит статистики в метаданных: min/max значения для каждой колонки. При запросе WHERE year = 2024 движок проверяет статистики каждого row group и пропускает те, где year не попадает в диапазон min–max.

Это работает аналогично partition pruning, но на уровне файла — без физического партиционирования.

Row Group 0: year min=2020, max=2022 → SKIP +
Row Group 1: year min=2023, max=2024 → READ (может содержать 2024)
Row Group 2: year min=2025, max=2025 → SKIP +

Эффективность pruning зависит от сортировки данных. Если строки отсортированы по year, каждый row group будет содержать узкий диапазон — pruning отсечёт большинство групп. Если данные случайные — каждый row group покрывает весь диапазон, и pruning бесполезен.

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

  1. Row Group — горизонтальный срез файла, содержащий все колонки для порции строк
  2. PAR1 magic number (4 байта) обрамляет файл с обоих концов, ридер начинает чтение с конца
  3. 128 MB — стандартный размер row group, баланс между параллелизмом и компрессией
  4. Параллелизм масштабируется с количеством row groups — каждый читается независимо
  5. Row group pruning по min/max статистикам пропускает целые группы строк без чтения данных
Spark: file formats и оптимизация storage ClickHouse: чтение Parquet из S3

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

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Parquet-файл весит 2 GB, содержит 16 row groups по 128 MB. На кластере 8 worker-нод. Как движок распределяет чтение?

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

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

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

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