Сжатие данных
Важную роль в обеспечении высокой производительности ADQM играет сжатие — или компрессия — данных (data compression). Например, с помощью сжатия можно уменьшить объем данных, считываемых при выполнении запроса, и тем самым ускорить этот запрос — см. пример в статье Повышение производительности запросов.
ADQM поддерживает сжатие данных для следующих табличных движков:
-
MergeTree — возможно установить алгоритм сжатия по умолчанию для таблиц, а также указать свой метод сжатия (или их комбинацию) для каждого отдельного столбца при создании/модификации таблицы (см. раздел Применение кодеков сжатия ниже).
-
Log — метод сжатия LZ4 используется по умолчанию, поддерживается возможность устанавливать сжатие по столбцам.
Кодеки сжатия данных
Алгоритм сжатия, применяемый к данным ADQM, определяется кодеком. В ADQM доступны следующие кодеки сжатия данных:
-
Кодеки общего назначения, позволяющие находить оптимальное соотношение между потреблением дискового пространства и ресурсов CPU.
-
Специализированные кодеки для определенных типов данных. Некоторые из этих кодеков не сжимают данные самостоятельно, а выполняют их предварительную обработку (учитывая особенности типа данных) для кодеков общего назначения, которые в свою очередь сжимают подготовленные данные эффективнее, чем неподготовленные.
Кодеки общего назначения
Кодек | Алгоритм сжатия | Уровень сжатия (level) |
---|---|---|
NONE |
Сжатие данных не применяется |
— |
LZ4 |
Алгоритм сжатия без потерь LZ4. Обеспечивает высокую скорость и хорошую степень сжатия. Используется по умолчанию |
— |
LZ4HC[(level)] |
Алгоритм LZ4 HC (high compression) с настраиваемым уровнем сжатия. По сравнению с LZ4 сжимает данные лучше, но медленнее, при этом обеспечивает такую же быструю декомпрессию |
Возможные уровни сжатия — |
ZSTD[(level)] |
Алгоритм сжатия ZSTD. Обеспечивает как скорость, так и высокую степень сжатия, которую можно настроить. Без применения специализированного кодека подготовки данных часто превосходит другие методы сжатия или, по крайней мере, конкурентоспособен |
Возможные уровни сжатия — Уровни сжатия выше |
ZSTD_QAT[(level)] |
Алгоритм сжатия ZSTD с настраиваемым уровнем сжатия, который реализуют Intel QATlib и Intel QAT ZSTD Plugin. Особенности использования:
|
Возможные уровни сжатия — |
DEFLATE_QPL |
Алгоритм сжатия Deflate, реализованный Intel Query Processing Library (Intel QPL). Особенности использования:
Техническая поддержка по этому кодеку для ADQM предоставляется в ограниченной форме |
— |
Специализированные кодеки
Кодек | Описание | Параметры |
---|---|---|
Delta(delta_bytes) |
Заменяет исходные значения разницей (дельтой) двух соседних значений (за исключением первого значения, которое остается неизменным). Хорошо работает с монотонно возрастающими значениями. Delta — кодек подготовки данных для дальнейшего сжатия, то есть его нельзя использовать отдельно (без дополнительного кодека сжатия) |
|
DoubleDelta(bytes_size) |
Вычисляет разницу между соседними дельтами и сохраняет ее в компактном бинарном виде. Оптимальная степень сжатия достигается для монотонных последовательностей с постоянным шагом (например, временных рядов). Может использоваться с любым типом данных фиксированного размера. Реализует алгоритм, используемый в Gorilla TSDB, адаптируя его для работы c 64-битными типами данных. Использует 1 дополнительный бит для 32-битных дельт: 5-битные префиксы вместо 4-битных. Подробнее читайте в разделе Compressing Time Stamps статьи Gorilla: A Fast, Scalable, In-Memory Time Series Database. DoubleDelta — кодек подготовки данных для дальнейшего сжатия, то есть его нельзя использовать отдельно (без дополнительного кодека сжатия) |
Возможные значения |
GCD |
Вычисляет наибольший общий знаменатель (Greatest Common Denominator, GCD) значений в столбце, затем делит каждое значение на GCD. Может использоваться с целочисленными, десятичными столбцами и столбцами типа DateTime. Также хорошо подходит для столбцов, значения которых изменяются (увеличиваются или уменьшаются) кратно GCD — например, GCD — кодек подготовки данных для дальнейшего сжатия, то есть его нельзя использовать отдельно (без дополнительного кодека сжатия) |
— |
Gorilla(bytes_size) |
Вычисляет XOR между текущим и предыдущим значением с плавающей запятой и записывает результат в компактной бинарной форме. Чем меньше разница между последовательными значениями (то есть чем медленнее изменяются значения ряда), тем лучше степень сжатия. Реализует алгоритм, используемый в Gorilla TSDB, адаптируя его для работы с 64-битными значениями. Дополнительную информацию можно найти в разделе Compressing values статьи Gorilla: A Fast, Scalable, In-Memory Time Series Database |
Возможные значения |
FPC(level, float_size) |
Повторно прогнозирует следующее значение с плавающей запятой в последовательности, используя лучший из двух предикторов, затем вычисляет XOR фактического значения с предсказанным значением и сжимает результат с ведущим нулем. Подобно Gorilla, FPC эффективно сохраняет ряды медленно изменяющихся значений с плавающей запятой. Для 64-битных значений FPC работает быстрее, чем Gorilla; для 32-битных значений — оценка может измениться. См. подробное описание алгоритма в статье High Throughput Compression of Double-Precision Floating-Point Data |
Возможные значения параметра Возможные значения |
T64 |
Обрезает неиспользуемые старшие биты целочисленных значений (включая Enum, Date и DateTime). На каждом шаге алгоритма кодек помещает блок из 64 значений в битовую матрицу размером 64x64, транспонирует ее, обрезает неиспользуемые биты значений и возвращает то, что осталось, в виде последовательности. Неиспользуемые биты — это биты, которые не изменяются от минимального к максимальному на всем диапазоне значений куска данных, для которого используется сжатие |
— |
Кодеки DoubleDelta и Gorilla используются в Gorilla TSDB в качестве компонентов алгоритма сжатия. Подход Gorilla эффективен в сценариях, когда данные представляют собой последовательность медленно меняющихся значений с их временными метками. Временные метки эффективно сжимаются кодеком DoubleDelta, а значения — кодеком Gorilla.
Применение кодеков сжатия
На уровне сервера
По умолчанию к столбцам таблиц семейства MergeTree ADQM применяет метод сжатия, определенный в конфигурации сервера. Изменить настройки сжатия по умолчанию можно в секции Data compression на странице конфигурации сервиса ADQMDB. Эта секция становится видимой при включенной опции Show advanced. Для доступа к параметрам конфигурации и их применения необходимо активировать переключатель Data compression.

После определения параметров сжатия данных нажмите Save и выполните действие Reconfig and restart для сервиса ADQMDB.
ПРИМЕЧАНИЕ
Изменение настроек сжатия по умолчанию не влияет на уже существующие таблицы. |
На уровне столбцов
Метод сжатия можно указать для каждого столбца отдельно в запросе CREATE TABLE с помощью выражения CODEC
:
CREATE TABLE <table_name>
( <column_name1> <data_type1> CODEC(<compression_codec1>) [...],
<column_name2> <data_type2> CODEC(<compression_codec2>) [...],
...)
ENGINE = MergeTree()
...;
Если для столбца указан кодек Default (CODEC(Default)
) или кодек не указан, используется алгоритм сжатия по умолчанию, установленный на уровне сервера.
Кодеки можно последовательно комбинировать — например, при использовании специализированного кодека, чтобы подготовить данные для более эффективного сжатия кодеком общего назначения (CODEC(Delta, ZSTD)
).
Изменить кодек сжатия столбца уже существующей таблицы можно с помощью следующего запроса:
ALTER TABLE <table_name> MODIFY COLUMN <column_name> CODEC(<new_compression_codec>);
Общие рекомендации
Для наиболее эффективного сжатия данных рекомендуется:
-
Выбирать наиболее подходящий под конкретную задачу алгоритм сжатия, учитывая тип и характер данных (если известны).
-
При выборе уровня сжатия данных следует помнить: чем выше этот уровень — тем больше, но дольше по времени сжатие данных. Фактически сжатие данных позволяет улучшить показатели I/O и уменьшить размер данных за счет ресурсов CPU. Постарайтесь найти оптимальные настройки — чтобы избежать длительного сжатия и медленного сканирования данных.
-
Конечная производительность сжатых таблиц зависит от множества факторов, включая аппаратное обеспечение, параметры запросов и так далее. Всегда проводите тестирование — чтобы определить, насколько эффективно сжатие данных в конкретном окружении.
РЕКОМЕНДАЦИЯ
Необходимо всегда соблюдать баланс между доступными ресурсами CPU и требуемой скоростью сжатия.
|
Пример
Создайте таблицу MergeTree со столбцами типа Int64 и Float64, применяя к ним кодеки сжатия данных LZ4 и ZSTD в комбинации с различными специализированными кодеками подготовки данных:
CREATE TABLE compression_test (
n Int32,
i64 Int64 DEFAULT n CODEC(NONE),
i64_lz4 Int64 DEFAULT n CODEC(LZ4),
i64_delta_lz4 Int64 DEFAULT n CODEC(Delta, LZ4),
i64_doubledelta_lz4 Int64 DEFAULT n CODEC(DoubleDelta, LZ4),
i64_t64_lz4 Int64 DEFAULT n CODEC(T64, LZ4),
i64_zstd Int64 DEFAULT n CODEC(ZSTD),
i64_delta_zstd Int64 DEFAULT n CODEC(Delta, ZSTD),
i64_doubledelta_zstd Int64 DEFAULT n CODEC(DoubleDelta, ZSTD),
i64_t64_zstd Int64 DEFAULT n CODEC(T64, ZSTD),
f64 Float64 DEFAULT n CODEC(NONE),
f64_lz4 Float64 DEFAULT n CODEC(LZ4),
f64_delta_lz4 Float64 DEFAULT n CODEC(Delta, LZ4),
f64_doubledelta_lz4 Float64 DEFAULT n CODEC(DoubleDelta, LZ4),
f64_gorilla_lz4 Float64 DEFAULT n CODEC(Gorilla, LZ4),
f64_fpc_lz4 Float64 DEFAULT n CODEC(FPC, LZ4),
f64_zstd Float64 DEFAULT n CODEC(ZSTD),
f64_delta_zstd Float64 DEFAULT n CODEC(Delta, ZSTD),
f64_doubledelta_zstd Float64 DEFAULT n CODEC(DoubleDelta, ZSTD),
f64_gorilla_zstd Float64 DEFAULT n CODEC(Gorilla, ZSTD),
f64_fpc_zstd Float64 DEFAULT n CODEC(FPC, ZSTD))
Engine = MergeTree()
ORDER BY tuple();
Сгенерируйте тестовые данные для таблицы (1 миллион строк) так, чтобы каждый столбец содержал монотонную последовательность чисел со случайным инкрементом:
INSERT INTO compression_test (n) SELECT number*1000+(rand()%100) FROM numbers(1000000);
Используйте системную таблицу system.columns, чтобы посмотреть размер данных в сжатом и несжатом виде для каждого столбца и кодеки сжатия столбцов:
SELECT
name,
type,
formatReadableSize(data_uncompressed_bytes) AS uncompressed,
formatReadableSize(data_compressed_bytes) AS compressed,
round(data_uncompressed_bytes / data_compressed_bytes, 2) AS ratio,
compression_codec codec
FROM system.columns
WHERE table = 'compression_test' AND name != 'n';
В результате этого тестирования видно, что применение специализированных кодеков может существенно повлиять на уровень сжатия данных кодеками общего назначения в зависимости от типа данных столбца. Например, для типа Int64 оба алгоритма (LZ4 и ZSTD) обеспечивают лучшее сжатие вместе с кодеком DoubleDelta, а для типа Float64 — ZSTD вместе с Delta или FPC.
┌─name─────────────────┬─type────┬─uncompressed─┬─compressed─┬─ratio─┬─codec───────────────────────┐ 1. │ i64 │ Int64 │ 7.63 MiB │ 7.63 MiB │ 1 │ CODEC(NONE) │ 2. │ i64_lz4 │ Int64 │ 7.63 MiB │ 4.78 MiB │ 1.6 │ CODEC(LZ4) │ 3. │ i64_delta_lz4 │ Int64 │ 7.63 MiB │ 2.89 MiB │ 2.64 │ CODEC(Delta(8), LZ4) │ 4. │ i64_doubledelta_lz4 │ Int64 │ 7.63 MiB │ 1.23 MiB │ 6.21 │ CODEC(DoubleDelta, LZ4) │ 5. │ i64_t64_lz4 │ Int64 │ 7.63 MiB │ 1.62 MiB │ 4.72 │ CODEC(T64, LZ4) │ 6. │ i64_zstd │ Int64 │ 7.63 MiB │ 1.97 MiB │ 3.87 │ CODEC(ZSTD(1)) │ 7. │ i64_delta_zstd │ Int64 │ 7.63 MiB │ 1.36 MiB │ 5.62 │ CODEC(Delta(8), ZSTD(1)) │ 8. │ i64_doubledelta_zstd │ Int64 │ 7.63 MiB │ 1.22 MiB │ 6.23 │ CODEC(DoubleDelta, ZSTD(1)) │ 9. │ i64_t64_zstd │ Int64 │ 7.63 MiB │ 1.42 MiB │ 5.36 │ CODEC(T64, ZSTD(1)) │ 10. │ f64 │ Float64 │ 7.63 MiB │ 7.63 MiB │ 1 │ CODEC(NONE) │ 11. │ f64_lz4 │ Float64 │ 7.63 MiB │ 5.01 MiB │ 1.52 │ CODEC(LZ4) │ 12. │ f64_delta_lz4 │ Float64 │ 7.63 MiB │ 2.90 MiB │ 2.63 │ CODEC(Delta(8), LZ4) │ 13. │ f64_doubledelta_lz4 │ Float64 │ 7.63 MiB │ 3.47 MiB │ 2.2 │ CODEC(DoubleDelta, LZ4) │ 14. │ f64_gorilla_lz4 │ Float64 │ 7.63 MiB │ 2.66 MiB │ 2.87 │ CODEC(Gorilla, LZ4) │ 15. │ f64_fpc_lz4 │ Float64 │ 7.63 MiB │ 3.11 MiB │ 2.45 │ CODEC(FPC(12), LZ4) │ 16. │ f64_zstd │ Float64 │ 7.63 MiB │ 2.22 MiB │ 3.44 │ CODEC(ZSTD(1)) │ 17. │ f64_delta_zstd │ Float64 │ 7.63 MiB │ 1.49 MiB │ 5.11 │ CODEC(Delta(8), ZSTD(1)) │ 18. │ f64_doubledelta_zstd │ Float64 │ 7.63 MiB │ 2.05 MiB │ 3.72 │ CODEC(DoubleDelta, ZSTD(1)) │ 19. │ f64_gorilla_zstd │ Float64 │ 7.63 MiB │ 2.32 MiB │ 3.29 │ CODEC(Gorilla, ZSTD(1)) │ 20. │ f64_fpc_zstd │ Float64 │ 7.63 MiB │ 1.87 MiB │ 4.08 │ CODEC(FPC(12), ZSTD(1)) │ └──────────────────────┴─────────┴──────────────┴────────────┴───────┴─────────────────────────────┘
При этом, например, на случайных данных Delta и DoubleDelta не очень хорошо работают как видно в примере ниже. Такие данные лучше сжимаются с использованием T64 для целочисленных значение и Gorilla для чисел с плавающей запятой — то есть эти кодеки могут быть рекомендованы к использованию, когда характер данных неизвестен.
CREATE TABLE compression_test_rand AS compression_test;
INSERT INTO compression_test_rand (n) SELECT rand()%(1000000) FROM numbers(1000000);
SELECT
name,
type,
formatReadableSize(data_uncompressed_bytes) AS uncompressed,
formatReadableSize(data_compressed_bytes) AS compressed,
round(data_uncompressed_bytes / data_compressed_bytes, 2) AS ratio,
compression_codec codec
FROM system.columns
WHERE table = 'compression_test_rand' AND name != 'n';
┌─name─────────────────┬─type────┬─uncompressed─┬─compressed─┬─ratio─┬─codec───────────────────────┐ 1. │ i64 │ Int64 │ 7.63 MiB │ 7.63 MiB │ 1 │ CODEC(NONE) │ 2. │ i64_lz4 │ Int64 │ 7.63 MiB │ 4.40 MiB │ 1.73 │ CODEC(LZ4) │ 3. │ i64_delta_lz4 │ Int64 │ 7.63 MiB │ 4.63 MiB │ 1.65 │ CODEC(Delta(8), LZ4) │ 4. │ i64_doubledelta_lz4 │ Int64 │ 7.63 MiB │ 4.43 MiB │ 1.72 │ CODEC(DoubleDelta, LZ4) │ 5. │ i64_t64_lz4 │ Int64 │ 7.63 MiB │ 2.40 MiB │ 3.18 │ CODEC(T64, LZ4) │ 6. │ i64_zstd │ Int64 │ 7.63 MiB │ 3.32 MiB │ 2.3 │ CODEC(ZSTD(1)) │ 7. │ i64_delta_zstd │ Int64 │ 7.63 MiB │ 3.42 MiB │ 2.23 │ CODEC(Delta(8), ZSTD(1)) │ 8. │ i64_doubledelta_zstd │ Int64 │ 7.63 MiB │ 3.84 MiB │ 1.99 │ CODEC(DoubleDelta, ZSTD(1)) │ 9. │ i64_t64_zstd │ Int64 │ 7.63 MiB │ 2.39 MiB │ 3.19 │ CODEC(T64, ZSTD(1)) │ 10. │ f64 │ Float64 │ 7.63 MiB │ 7.63 MiB │ 1 │ CODEC(NONE) │ 11. │ f64_lz4 │ Float64 │ 7.63 MiB │ 4.67 MiB │ 1.63 │ CODEC(LZ4) │ 12. │ f64_delta_lz4 │ Float64 │ 7.63 MiB │ 4.85 MiB │ 1.57 │ CODEC(Delta(8), LZ4) │ 13. │ f64_doubledelta_lz4 │ Float64 │ 7.63 MiB │ 5.94 MiB │ 1.28 │ CODEC(DoubleDelta, LZ4) │ 14. │ f64_gorilla_lz4 │ Float64 │ 7.63 MiB │ 3.12 MiB │ 2.44 │ CODEC(Gorilla, LZ4) │ 15. │ f64_fpc_lz4 │ Float64 │ 7.63 MiB │ 5.03 MiB │ 1.52 │ CODEC(FPC(12), LZ4) │ 16. │ f64_zstd │ Float64 │ 7.63 MiB │ 3.26 MiB │ 2.34 │ CODEC(ZSTD(1)) │ 17. │ f64_delta_zstd │ Float64 │ 7.63 MiB │ 3.44 MiB │ 2.22 │ CODEC(Delta(8), ZSTD(1)) │ 18. │ f64_doubledelta_zstd │ Float64 │ 7.63 MiB │ 4.07 MiB │ 1.87 │ CODEC(DoubleDelta, ZSTD(1)) │ 19. │ f64_gorilla_zstd │ Float64 │ 7.63 MiB │ 3.05 MiB │ 2.5 │ CODEC(Gorilla, ZSTD(1)) │ 20. │ f64_fpc_zstd │ Float64 │ 7.63 MiB │ 4.20 MiB │ 1.82 │ CODEC(FPC(12), ZSTD(1)) │ └──────────────────────┴─────────┴──────────────┴────────────┴───────┴─────────────────────────────┘