Основы кодирования данных
Кодирование ≠ Компрессия
Кодирование (encoding) и компрессия (compression) часто путают, но это разные стадии конвейера:
- Кодирование — преобразует данные в более компактное представление, сохраняя семантику. Закодированные данные можно читать без полной декомпрессии.
- Компрессия — применяет общий алгоритм сжатия (Snappy, Zstd) к уже закодированным данным. Результат — бинарный blob, который нужно полностью распаковать.
Кодирование работает до компрессии и использует знание о типе данных. Компрессия работает после и обрабатывает данные как поток байтов.
Raw данные колонки
Исходные значения колонки — например, 1M строк с колонкой departmentЗакодированные данные (меньше, но читаемы)
Encoding использует знание о типе: dictionary для строк с повторами, delta для монотонных чисел, RLE для серийСжатые данные (минимальный размер)
Компрессия (Snappy/Zstd) сжимает уже компактные данные. Результат — binary blob для храненияDictionary Encoding
Самая распространённая кодировка для строковых данных с повторяющимися значениями.
Идея: вместо хранения полной строки каждый раз — создать словарь уникальных значений и заменить каждое вхождение на индекс в словаре.
До кодирования
После кодирования
Когда эффективно: колонка с низкой кардинальностью (мало уникальных значений). Типичные примеры: country, status, category, department.
Когда неэффективно: колонки с высокой кардинальностью (UUID, email, free-text). Словарь становится размером с оригинальные данные.
Parquet автоматически применяет dictionary encoding к каждой колонке. Если словарь превышает порог (по умолчанию 1 MB), Parquet переключается на plain encoding (fallback). Вы можете контролировать этот порог при записи.
Run-Length Encoding (RLE)
Заменяет последовательности одинаковых значений на пару (значение, количество).
До RLE
После RLE
Когда эффективно: отсортированные данные или данные с длинными “сериями” одинаковых значений. Partition columns в Parquet — идеальный кандидат.
Когда неэффективно: случайно распределённые данные без повторяющихся серий.
RLE часто комбинируется с dictionary encoding. Сначала значения заменяются на индексы словаря, затем серии одинаковых индексов кодируются RLE. Parquet использует именно эту комбинацию — RLE_DICTIONARY.
Delta Encoding
Хранит разницу между последовательными значениями вместо самих значений.
До delta encoding
После delta encoding
Когда эффективно: монотонно растущие значения — timestamps, auto-increment IDs, event counters. Дельты маленькие → помещаются в меньше битов.
Когда неэффективно: случайные данные, где дельты такие же большие, как исходные значения.
Bit-Packing
Использует ровно столько битов, сколько нужно для представления значения, вместо стандартных 32 или 64 бит.
Если все значения в колонке помещаются в диапазон 0–15, нужно всего 4 бита на значение вместо 32:
Стандартное хранение (int32)
Bit-packed (4 бита)
Bit-packing часто применяется после dictionary encoding — индексы словаря обычно маленькие числа, которые помещаются в несколько бит.
Как кодировки комбинируются
Реальные форматы применяют несколько кодировок последовательно:
Raw строки: Engineering, Sales, Engineering, HR…
Исходные строковые значения с повторами — department, country, status и подобные колонкиИндексы: 0, 1, 0, 2, 0, 1, 0, 0, 2, 1…
Строки заменяются на числовые индексы словаря. Словарь: 0=Engineering, 1=Sales, 2=HRRLE: (0, 3), (1, 1), (0, 2), (2, 1)…
Серии одинаковых индексов сжимаются в пары (значение, длина). Эффективно на отсортированных данных.Packed: 2 бита на индекс
Индексы, которые не попали в RLE-серии, упаковываются по минимуму бит. 4 значения = 2 бита.Сжатый бинарный блок
Финальная компрессия общим алгоритмом. На уже закодированных данных даёт дополнительные 1.5–3x.Ключевые выводы
- Кодирование использует знание о типе данных. Компрессия работает с байтами вслепую. Кодирование идёт первым.
- Dictionary encoding — для строк с повторами. Заменяет строки на маленькие числа. 10–100x сжатие на низкой кардинальности.
- RLE — для серий одинаковых значений. Максимально эффективен на отсортированных данных.
- Delta encoding — для монотонных последовательностей (timestamps, IDs). Хранит маленькие дельты вместо больших значений.
- Bit-packing — использует минимум бит. Часто применяется поверх dictionary индексов.
- Реальные форматы комбинируют кодировки: dictionary → RLE → bit-packing → compression.