Learning Platform
Глоссарий Troubleshooting
Урок 02.05 · 20 мин
Средний
CompressionLZ4ZSTDDeltaGorilla

Кодеки сжатия

Правильный выбор кодека сжатия по типу столбца может уменьшить объём хранения в 10 раз и ускорить запросы (меньше I/O). ClickHouse поддерживает конвейеры кодеков — несколько кодеков, применяемых последовательно. Кодек задаётся в DDL для каждого столбца.


Доступные кодеки

Кодеки ClickHouse: сравнение по назначению
КодекКодек: название алгоритма. Кодеки делятся на две группы: кодеки данных (Delta, DoubleDelta, Gorilla, T64 — преобразуют данные перед сжатием) и кодеки сжатия (LZ4, ZSTD — собственно сжимают). Рекомендуется комбинировать: сначала кодек данных, затем кодек сжатия.
Лучше всего дляЛучше всего подходит для: типы данных и паттерны, при которых кодек даёт максимальный эффект. Применение кодека к неподходящим данным может ухудшить результат.
Степень сжатияСтепень сжатия: насколько кодек уменьшает объём данных. Высокая степень сжатия = меньше I/O при чтении, но потенциально больше CPU на распаковку.
СкоростьСкорость: скорость сжатия и распаковки. Для OLAP-запросов важнее скорость распаковки — данные читаются чаще, чем пишутся.
ПрименениеТипичное применение: конкретные сценарии, где кодек показывает себя лучше всего. Используйте как отправную точку, затем измерьте на реальных данных.
LZ4DefaultLZ4: кодек сжатия общего назначения. Используется по умолчанию если кодек не указан явно. Алгоритм LZ4 — block-oriented lossless compression. Чрезвычайно быстрая распаковка (~3 GB/s на одном ядре). Хорошая степень сжатия для большинства данных.
Большинство столбцовСредняяОчень быстроВсе столбцы без особых требований
ZSTD(N)N=1..22ZSTD: Zstandard — алгоритм сжатия с настраиваемым уровнем. N=1 — быстро, хорошее сжатие. N=3 — рекомендуемый баланс. N=22 — максимальное сжатие, очень медленно. Для read-heavy таблиц используйте N=1-3: высокие уровни замедляют распаковку и убивают latency запросов.
Архивные данные, строкиВысокая (ZSTD(3))Медленнее LZ4Холодные данные, URL, строки высокой кардинальности
DeltaКодек данныхDelta: преобразует значения в разности между соседними значениями. Вместо [100, 101, 102, 103] хранит [100, 1, 1, 1]. Для монотонно возрастающих последовательностей (счётчики, timestamp в Unix time) разности близки к константе — последующее LZ4/ZSTD сжимает их почти идеально.
Монотонные целые, timestampОчень высокая (с LZ4/ZSTD)БыстроDateTime, auto-increment ID, Unix epoch
DoubleDeltaКодек данныхDoubleDelta: разности разностей (вторые производные). Для данных с регулярным интервалом (IoT-сенсоры, метрики с фиксированным шагом) первые дельты почти одинаковы, вторые — почти нули. Это обеспечивает исключительное сжатие для временных рядов с равномерным интервалом.
IoT, метрики с фиксированным интерваломОтлично для IoTБыстроTimestamp с фиксированным шагом (каждые 10 сек)
GorillaКодек данныхGorilla: кодек для float-значений. Использует XOR между соседними значениями — для медленно меняющихся float (температура, цена, метрики) XOR даёт много нулей и повторяющихся паттернов. Вдохновлён оригинальным Gorilla TSDB (Facebook). Эффективен когда значение меняется незначительно между соседними строками.
Float с малыми изменениямиВысокая для сенсорных данныхБыстроТемпература, цена акции, метрики CPU/RAM
T64Кодек данныхT64: транспонирует матрицу битов 64 значений. Эффективен для целых чисел с ограниченным диапазоном значений, где старшие биты одинаковы. При диапазоне 0..255 все значения помещаются в 8 бит — T64 хранит только значимые биты, остальные 56 бит на значение отбрасывает.
Целые с ограниченным диапазономВысокаяОчень быстроEnum-like целые, статус-коды, малые счётчики

Конвейеры кодеков

CODEC(Delta, ZSTD(3)) — конвейер из двух кодеков. Применяются слева направо:

  1. Delta — преобразует исходные значения в разности (кодек данных)
  2. ZSTD(3) — сжимает поток разностей (кодек сжатия)

Почему это работает: Delta encoding для монотонных данных превращает последовательность вида [1000000, 1000001, 1000002, ...] в [1000000, 1, 1, 1, ...]. Затем ZSTD сжимает последовательность из почти одинаковых маленьких значений практически идеально.

-- Пример объявления кодеков в DDL таблицы
CREATE TABLE metrics (
    ts DateTime64(3)   CODEC(DoubleDelta, LZ4),
    user_id UInt32     CODEC(Delta, LZ4),
    session_id UInt64  CODEC(Delta, ZSTD(1)),
    temperature Float64 CODEC(Gorilla, LZ4),
    status_code UInt8  CODEC(T64, LZ4),
    url String         CODEC(ZSTD(3))
) ENGINE = MergeTree()
ORDER BY (ts, user_id);

Практические рекомендации по типам столбцов

Тип столбцаРекомендуемый кодекПочему
DateTime / DateTime64 с регулярным интерваломCODEC(DoubleDelta, LZ4)Регулярный интервал = константные вторые дельты
DateTime / DateTime64 с нерегулярным интерваломCODEC(Delta, ZSTD(1))Первые дельты малы, ZSTD(1) быстрый
UInt32 / UInt64 счётчик (монотонный)CODEC(Delta, LZ4)Разности ~1, LZ4 сжимает идеально
UInt32 / UInt64 ограниченного диапазонаCODEC(T64, LZ4)Малый диапазон = мало значимых бит
Float64 медленно меняющийсяCODEC(Gorilla, LZ4)XOR между соседними значениями даёт много нулей
String URL, путь (высокая кардинальность)CODEC(ZSTD(3))ZSTD даёт хорошее сжатие для строк
По умолчанию (без явного кодека)LZ4Применяется автоматически

Измерение степени сжатия

Прежде чем менять кодеки, измерьте реальную ситуацию:

-- Степень сжатия по столбцам
SELECT
    column,
    formatReadableSize(data_compressed_bytes) AS compressed,
    formatReadableSize(data_uncompressed_bytes) AS uncompressed,
    round(data_uncompressed_bytes / data_compressed_bytes, 2) AS ratio
FROM system.columns
WHERE table = 'your_table'
ORDER BY data_uncompressed_bytes DESC;

-- Детально по parts и столбцам
SELECT
    column,
    sum(column_data_compressed_bytes) AS compressed,
    sum(column_data_uncompressed_bytes) AS uncompressed,
    round(sum(column_data_uncompressed_bytes) / sum(column_data_compressed_bytes), 2) AS ratio
FROM system.parts_columns
WHERE table = 'your_table' AND active = 1
GROUP BY column
ORDER BY uncompressed DESC;

После смены кодека ALTER TABLE не перепишет существующие parts — изменения применяются только к новым parts. Для полной перезаписи используйте ALTER TABLE ... MATERIALIZE COLUMN или OPTIMIZE TABLE ... FINAL (в dev среде).

TIP

Начинайте с настроек по умолчанию (LZ4). Меняйте кодеки только после измерений на реальных данных. Преждевременная оптимизация кодеков редко окупается: эффект проявляется только на характерных паттернах данных. Gorilla на случайных float ничем не лучше LZ4.

Compression internals — глубокий разбор LZ4 vs ZSTD Integer encodings — Delta, DoubleDelta, FOR, RLE

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

  1. LZ4 по умолчанию — хороший выбор для большинства столбцов. Меняйте только с измерениями.
  2. Конвейер L-to-R: CODEC(Delta, ZSTD(3)) — сначала Delta (кодек данных), затем ZSTD (сжатие).
  3. Delta + LZ4/ZSTD — для монотонных целых и timestamp с нерегулярным шагом.
  4. DoubleDelta — для IoT и метрик с фиксированным интервалом выборки.
  5. Gorilla — для float, меняющихся плавно (температура, цена, метрики).
  6. ZSTD(N) высокого уровня (N=10+) — только для архивных, редко читаемых данных. Высокие уровни замедляют распаковку и увеличивают latency запросов.

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

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Столбец хранит показания температуры IoT-сенсора: значения меняются на 0.1–0.3 градуса в секунду (Float64). Какой кодек даст наилучшее сжатие для этого столбца?

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

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

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

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