Использование сжатия

Документ представляет алгоритмы сжатия, используемые в YMatrix, и способы их применения.

Общий алгоритм сжатия

Понятие

Общее сжатие — это алгоритм сжатия, который напрямую сжимает блоки данных, не имея представления о внутренней структуре данных. Такое сжатие часто основано на особенностях двоичных данных для уменьшения избыточности хранимых данных, при этом сжатые данные не могут быть доступны случайным образом. Сжатие и распаковка должны выполняться целиком, блоками данных.

YMatrix поддерживает три алгоритма сжатия для блоков данных: zlib, lz4 и zstd.

Использование

Три алгоритма общего сжатия — lz4, zstd и zlib — должны быть указаны в операторе WITH при создании таблиц. Примеры:

=# WITH (compresstype=zstd, compresslevel=3, compress_threshold=1200)

Примечание!
Дополнительную информацию об использовании оператора WITH см. в разделе CREATE TABLE.

Параметры:

Имя параметра Значение по умолчанию Минимальное значение Максимальное значение Описание
compress_threshold 1200 1 8000 Порог сжатия. Определяет, сколько кортежей (tuples) сжимается в одной таблице, и является верхним пределом числа сжимаемых кортежей в одном блоке.
compresstype none Алгоритм сжатия, поддерживаемые значения:
1. zstd
2. zlib
3. lz4
compresslevel 0 1 Уровень сжатия. Чем меньше значение, тем быстрее сжатие, но хуже результат; чем больше значение, тем медленнее сжатие, но лучше результат. Разные алгоритмы имеют разные допустимые диапазоны значений:
zstd: 1–19
zlib: 1–9
lz4: 1–20

Примечание!
Если compresslevel > 0 и compresstype не указаны, по умолчанию используется compresstype = zlib.
Если указан compresstype, но не указан compresslevel, по умолчанию используется compresslevel = 1.

Примечание!
Как правило, чем выше уровень сжатия, тем выше коэффициент сжатия и ниже скорость. Однако это не абсолютное правило.

Кодирующая цепочка

Помимо общих алгоритмов сжатия, рекомендуем попробовать собственный разработанный YMatrix алгоритм сжатия — кодирующую цепочку (mxcustom).

Понятие

В отличие от общего сжатия, основа кодирующей цепочки — это алгоритмы сжатия, которые учитывают формат и семантику данных внутри блока. В реляционной базе данных данные организованы в виде таблиц, и каждый столбец имеет фиксированный тип данных, что обеспечивает логическую схожесть данных в одном столбце. Кроме того, в некоторых сценариях данные соседних строк в бизнес-таблице также могут быть очень похожи. Поэтому, если данные сжимаются по столбцам и хранятся вместе, это обеспечивает лучший эффект сжатия.

Кодирующая цепочка обладает следующими возможностями:

  • Поддерживает множество алгоритмов кодирования/сжатия. Для разных типов данных разработаны специализированные алгоритмы, учитывающие их особенности. Разные алгоритмы имеют разные характеристики: применимость, коэффициент сжатия, скорость. Точная настройка алгоритмов позволяет добиться отличного результата сжатия.
  • Комбинированное сжатие. Алгоритмы, основанные на типе данных, могут быть дополнительно объединены с общими алгоритмами для достижения еще лучшего результата.
  • Столбцовое сжатие. Кодирующая цепочка позволяет задавать разные комбинации сжатия для каждого столбца, раскрывая возможности тонкой настройки. Можно указать несколько алгоритмов сжатия для одного столбца, реализуя многоуровневое сжатие.

Преимущества

Кодирующая цепочка демонстрирует явные преимущества при сжатии временных рядов. Данные временных рядов обладают характерными особенностями: регулярные временные интервалы, независимость между столбцами, постепенность изменения во времени и т.д. Общие алгоритмы сжатия, такие как lz4 и zstd, ориентированы на потоки байтов и не учитывают эти особенности, поэтому их результат часто далек от идеального.

Кодирующая цепочка эффективно использует особенности данных временных рядов для глубокого сжатия таблиц. Преимущества глубокого сжатия:

  • Значительная экономия затрат на хранение. Уменьшение размера данных значительно снижает стоимость хранения, позволяя разместить больше данных на том же оборудовании и сохранить больше данных.
  • Снижение нагрузки на диск I/O. Благодаря уменьшению объема данных снижается нагрузка на диск I/O. Это особенно заметно при запросах, требующих большого количества операций чтения/записи, особенно на жестких дисках (HDD), в сценариях с «холодными» данными (редко запрашиваемыми).
  • Глубокая оптимизация, ускорение запросов. Целевые алгоритмы сжатия проще и позволяют глубже оптимизировать процесс, что обеспечивает более быструю распаковку и дополнительное ускорение запросов.

Ограничения

  • Особенности кодирующей цепочки делают её методом, тесно связанным с характеристиками данных, а не универсальным решением, и требуют осторожного выбора алгоритма.
  • Кодирующая цепочка применима только к таблицам MARS2 и MARS3.

Примечание!
Самый простой способ использовать кодирующую цепочку — включить режим адаптивного кодирования (adaptive coding), который автоматически определяет характеристики данных во время выполнения и выбирает подходящий метод кодирования. Подробности ниже.

Использование

Основные способы использования кодирующей цепочки представлены в таблице:

Номер Использование
1 Сжатие на уровне столбца
2 Сжатие на уровне таблицы (поддерживает изменение алгоритма)
3 Одновременное указание сжатия на уровне таблицы и столбца
4 Адаптивное кодирование (AutoEncode)

Подробное описание ниже. Независимо от выбранного способа, необходимо сначала создать расширение:

=# CREATE EXTENSION matrixts;

Сжатие на уровне столбца

Настройка пользовательских параметров сжатия для каждого столбца таблицы t1. encodechain используется для указания комбинаций кодирования (можно указать один или несколько алгоритмов). Если указано несколько алгоритмов, они разделяются запятыми. Пример:

=# CREATE TABLE t1(
   f1 int8 ENCODING(encodechain='deltadelta(7), zstd', compresstype='mxcustom'),
   f2 int8 ENCODING(encodechain='lz4', compresstype='mxcustom')
   )
   USING MARS3
   ORDER BY (f1);

Следующий SQL-запрос также позволяет задать сжатие на уровне столбца:

=# CREATE TABLE t1_1(
   f1 int8,COLUMN f1 ENCODING (encodechain='lz4, zstd', compresstype='mxcustom'),
   f2 int8,COLUMN f2 ENCODING(encodechain='lz4', compresstype='mxcustom')
   )
   USING MARS3
   ORDER BY (f1);

DEFAULT COLUMN ENCODING означает, что по умолчанию для всех столбцов задается один и тот же алгоритм сжатия — это эквивалентно сжатию на уровне таблицы.

=# CREATE TABLE t1_2(
   f1 int8,
   f2 int8,
   DEFAULT COLUMN ENCODING (encodechain='auto', compresstype='mxcustom')
   )
   USING MARS3
   ORDER BY (f1);

Сжатие на уровне таблицы

Предположим, вы хотите применить алгоритм сжатия zstd к таблице t2 на уровне таблицы. Есть два варианта: использовать кодирующую цепочку или не использовать её. Основное различие в том, что использование кодирующей цепочки позволяет после создания таблицы изменить алгоритм сжатия с помощью SQL-запросов.

Пример применения кодирующей цепочки для сжатия таблицы t2_1 с использованием алгоритма zstd:

=# CREATE TABLE t2_1 (
   f1 int8,
   f2 int8
   ) 
   USING MARS3
   WITH(
   compresstype='mxcustom',
   encodechain='zstd'
   )
   ORDER BY (f1);

Пример комбинированного сжатия таблицы t2_2 с использованием алгоритма zstd, lz4:

=# CREATE TABLE t2_2 (
   f1 int8,
   f2 int8
   ) 
   USING MARS3
   WITH(
   compresstype='mxcustom',
   encodechain='zstd, lz4'
   )
   ORDER BY (f1);   

Изменение алгоритма сжатия на уровне таблицы на адаптивное кодирование:

=# ALTER TABLE t2_1 SET (encodechain='auto');

Одновременное указание сжатия на уровне таблицы и столбца

В Примере 1 для таблицы auto задан алгоритм сжатия lz4, а для столбца t3_1 — алгоритм f1. Поскольку параметры сжатия на уровне столбца имеют приоритет над параметрами на уровне таблицы, столбец f1 будет сжат с использованием указанного алгоритма, а остальные столбцы (f2) таблицы t3_1 будут сжаты адаптивно.

=# CREATE TABLE t3_1 (
   f1 int8 ENCODING(compresstype='lz4'),
   f2 int8
   ) 
   USING MARS3
   WITH(
   compresstype='mxcustom',
   encodechain='auto'
   )
   ORDER BY (f1);

В Примере 2 для таблицы auto задан алгоритм сжатия lz4, deltazigzag, а для столбца t3_2 — алгоритм f1.

=# CREATE TABLE t3_2 (
   f1 int8 ENCODING(compresstype='mxcustom', encodechain='lz4, deltazigzag'),
   f2 int8
   ) 
   USING MARS3
   WITH(
   compresstype='mxcustom',
   encodechain='auto'
   )
   ORDER BY (f1);   

Адаптивное кодирование

Кодирующая цепочка YMatrix поддерживает адаптивное кодирование: система во время выполнения анализирует характеристики данных и автоматически выбирает оптимальный набор методов кодирования.

Применение адаптивного кодирования на уровне таблицы для таблицы t4:

=# CREATE TABLE t4 (
   f1 int8,
   f2 int8
   ) 
   USING MARS3
   WITH(
   compresstype=mxcustom
   )
   ORDER BY (f1);

Также можно явно указать кодирующую цепочку как auto, выбрав один из двух способов:

=# CREATE TABLE t4 (
   f1 int8,
   f2 int8
   ) 
   USING MARS3
   WITH(
   compresstype=mxcustom,
   encodechain=auto
   )
   ORDER BY (f1);

Укажите адаптивное кодирование на уровне таблицы lz4 и на уровне столбца для таблицы t4. В этом случае столбец f2 будет сжат адаптивно, так как для него не указан конкретный алгоритм.

=# CREATE TABLE t5 (
   f1 int8 ENCODING (
              compresstype=mxcustom,
              encodechain=auto
              ),
   f2 int8
   ) 
   USING MARS3
   WITH(
   compresstype=mxcustom,
   encodechain=lz4
   )
   ORDER BY (f1);

В режиме адаптивного кодирования на уровне таблицы поддерживается Automode с двумя вариантами: приоритет коэффициента сжатия и приоритет скорости. В примере для таблицы t4 включен режим приоритета коэффициента сжатия. automode=1 означает приоритет коэффициента сжатия, automode=2 — приоритет скорости.

-- automode=1, auto for cost
-- automode=2, auto for speed
=# CREATE TABLE t6 (
   f1 int8,
   f2 int8
   ) 
   USING MARS3
   WITH(
   compresstype=mxcustom,
   automode=1
   )
   ORDER BY (f1);

Примечание!
Адаптивное кодирование нельзя одновременно указывать вместе с другими алгоритмами сжатия.

Приложение: Алгоритмы сжатия

Алгоритм Поддерживаемые параметры Описание
lz4 & zstd compresslevel Кодирующая цепочка включает lz4 и zstd в комбинации кодирования, используя системные библиотеки сжатия. lz4 подходит для сценариев, где важна скорость, особенно скорость распаковки. zstd более сбалансирован. При стандартном уровне сжатия скорость распаковки lz4 значительно выше, чем у zstd, а коэффициент сжатия zstd явно выше. Как правило, чем выше уровень сжатия zstd, тем выше коэффициент сжатия и ниже скорость. Однако это не абсолютное правило.
deltadelta Масштабирующий коэффициент (опционально). Масштабирующий коэффициент — это количество смещаемых бит. Например, deltadelta(7) означает, что разница масштабируется на 7 бит, а затем сохраняется. По умолчанию масштабирование не применяется Принцип Delta — вычисление второй разности между соседними значениями, особенно эффективно для отсортированных временных меток. Результат обработки строго упорядоченной последовательности временных меток без пропусков — последовательность нулей, что обеспечивает отличное сжатие. Если некоторые временные метки отсутствуют, разница может остаться большой. deltadelta поддерживает только целые числа и подходит для случаев, когда вторая разность — небольшое целое число.
deltazigzag Масштабирующий коэффициент (опционально) Принцип deltazigzag: вычисление разницы, затем преобразование возможных отрицательных чисел в положительные с помощью zigzag, далее сжатие с использованием кодирования переменной длины. Подходит для последовательностей целых чисел с небольшими интервалами, без требований к сортировке.
Gorilla Кодирование Gorilla используется для сжатия чисел с плавающей запятой. Принцип — выполнение операции XOR между текущим и предыдущим значением для сжатия нулевых префиксов и суффиксов. В настоящее время поддерживается только тип double (8 байт).
Gorilla2 Оптимизированная версия Gorilla. Gorilla2 лучше улавливает распространённые характеристики данных. В большинстве временных сценариев коэффициент сжатия Gorilla2 значительно выше, чем у Gorilla. Кроме того, Gorilla2 по коэффициенту сжатия и времени сжатия сопоставим с zstd, но превосходит его по скорости распаковки. Поддерживает типы float4 и float8.
Floatint Масштабирующий коэффициент (обязательный) В некоторых случаях сжатие чисел с плавающей запятой с помощью Gorilla неэффективно. Например, в сценарии IoT, где координаты автомобиля — медленно меняющиеся значения с плавающей запятой, коэффициент сжатия Gorilla почти нулевой. Комбинация floatint и deltadelta может дать более чем в 10 раз лучший результат. Это объясняется особым внутренним представлением чисел с плавающей запятой: изменения соседних значений малы, XOR не даёт много нулей, но целочисленная последовательность после масштабирования сохраняет схожесть и легче сжимается. Важно: масштабирование floatint вносит погрешность, величина которой зависит от масштабирующего коэффициента. Например, при коэффициенте 4 максимальная погрешность составляет 0.0001.
simple8b simple8b подходит для целых чисел с небольшим диапазоном. Принцип — хранение нескольких малых целых чисел в 8 байтах. Например, если данные содержат целые числа < 8, то каждые 3 числа помещаются в один байт, обеспечивая лучшее сжатие. В таких случаях lz4 может давать плохой результат из-за нерегулярности данных.
fds В сценариях временных рядов часто используются числа с плавающей запятой для хранения целочисленной информации. fds — специальный код, разработанный для этого случая. Он определяет, что данные на самом деле являются целыми числами, преобразует их в двоичные целые и дополнительно сжимает. На наборе данных TSBS cpu-only (всего 13 столбцов, из них 10 числовых — случайные целые числа, хранящиеся как float8), коэффициент сжатия fds в 2 раза выше, чем у zstd (размер после сжатия составляет 30% от размера zstd).