MSSQL: сравниваем data compression и backup compression

MSSQL поддерживает компрессию бэкапов на лету - легковесную и быструю. Также данные можно упаковать внутри базы с помощью DATA_COMPRESSION = PAGE или ROW. Как мы помним, упакованные данные плохо пакуются. Как упаковка данных повлияет на размер бэкапа?

Тестовая база

Создаем большую табличку test в чистой базе (не забываем перевести ее в SIMPLE):

create table seed (n int)
GO
set nocount on
declare @n int=9999 while @n>=0 begin
  insert into seed select @n
  set @n=@n-1
  end
GO
create table test (n int identity, a int, b int, str varchar(128))
GO
create clustered index PK_n on test (n)
GO
insert into test (a,b,str)
  select L.n,R.n,'seed '+convert(varchar,L.n)+' and '+convert(varchar,R.n)
    from seed L, seed R
GO
create index IXa on test (a)
GO
create index IXb on test (b)
GO
create index IXstr on test (str)
GO

Запишем размеры индексов и бэкапов - упакованного и обычного. Затем применим ко всем индексам DATA_COMPRESSION = PAGE

alter index PK_n on test REBUILD with (data_compression=PAGE)
alter index IXa on test REBUILD with (data_compression=PAGE)
alter index IXb on test REBUILD with (data_compression=PAGE)
alter index IXstr on test REBUILD with (data_compression=PAGE)

и снова все запишем.

Наконец, применим DATA_COMPRESSION = ROW

alter index PK_n on test REBUILD with (data_compression=ROW)
alter index IXa on test REBUILD with (data_compression=ROW)
alter index IXb on test REBUILD with (data_compression=ROW)
alter index IXstr on test REBUILD with (data_compression=ROW)

Результаты

Все размеры приведены в Mb

Index

no compression

compression PAGE

compression ROW

PK_n

4355

1992

3646

IXa

1355

854

1152

IXb

1355

963

1152

IXstr

3091

1239

3174

Теперь рассмотрим размер full backups, тоже в мегабайтах:

Backup

no compression

compression PAGE

compression ROW

no compression

10417

5189

9364

compression

1934

2331

2285

Выводы

Америку я не открыл, результаты довольно ожидаемые, но хотелось убедиться еще раз

@Tzimie
03.03.2024 18:52 UTC
Первоисточник

Комментарии

@dyadyaSerezha
03.03.2024 16:34 UTC
0

Непонятен смысл заголовка - зачем это сравнивать? Такое ощущение, что БД и бэкап(ы) хранятся на одном диске и очень надо по максимуму сжать все данные. Это так?

@Tzimie
03.03.2024 16:53 UTC
0

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

Бэкап конечно хранится в другом месте. Но его размер тоже важен. Если, например, как у нас, базы 95тб и бэкап идёт двое суток. Вы тогда очень будете беспокоиться о размере

03.03.2024 20:05 UTC
+2

По-моему, бэкапить уже сжатые данные всегда быстрее, потому что их просто меньше, а 90% потери скорости - это сеть. И обычно место на бэкапе не так дорого/важно, как на проде.

04.03.2024 07:50 UTC
+1

Здесь скорость не всегда первична. Если делать нормальную структуру хранения бэкапов, типа трехуровневой. то объем занимаемого места очень даже важен, особенно для больших баз. А сам бэкап обычно идет с аппаратного снапшота, и время бэкапа так не так чтобы очень критично.
Во всяком случае, я бы выбрал на 10% меньше места в долгосрочном хранении, чем на 15% быстрее скорость бэкапа.

04.03.2024 07:58 UTC
0

Не слышал даже про аппаратный снэпшот, но автор написал что бэкап идёт 2 суток.

04.03.2024 08:22 UTC
0

У нас чисто железные сервера с локальными SSD, так как экстремальные нагрузки, так что бэкапы у нас обычные

04.03.2024 08:36 UTC
+2

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

Как вариант поднимать асинхронный AlwaysOn и снимать бэкап со второй реплики, а не с рабочего сервера. На время бэкапа будет отставние слейва от мастера, но потом догонит.

04.03.2024 08:55 UTC
0
  1. Локов там нет, там уменьшается место в LDF так как на время Full backup лог не может быть забэкаплен (что логично)

  2. нагрузка да, увеличивается, и CPU тоже

  3. При таких объемах, как вы понимаете, AlwaysOn есть всегда. Правда не везде у нас Enterprise.

@speshuric
04.03.2024 10:50 UTC
+1

Сжатие на уровне строк полезно по факту только если много числовых (numeric) полей с нулями или небольшими значениями (при больших допустимых). Тогда все эти нули будут храниться компактно. Другие выгодные варианты придумать можно, конечно, но базовый, наверное, такой.

Сжатие на уровне страниц - если есть много повторяющихся (но не длинных строковых/бинарных) значений. Повторения могут быть частичными. Способ сжатия описан тут. Доступ к таким данным на чтение и запись дороже по CPU, но для таблиц с кучей похожих чисел и ссылками на другие записи (всеми типовыми способами: уидами, строками, числами, бинарными) жмутся очень хорошо и это часто даёт такой выигрыш при чтении/записи с диска, что становится оправданным. Даже для неплохих систем хранения.

Сжатие бэкапов явно алгоритм не описан, но судя по появлению в 2022 выбора между MS_XPRESS (по умолчанию) and QAT_DEFLATE (для аппаратного ускорения) и по некоторым другим признакам - штатный алгоритм сильно похож на обычный deflate - умеренно хорошо подходит для любых избыточных потоков.

Отсюда уже можно сделать все выводы данной статьи, но по другим соображениям :) Плюс есть всякие хитрозадые опции хранения типа sparse columns, column sets, columnstore indexes и другие. Плюс есть еще соображения разницы между Standard/Enterprise.

И есть еще куча граничных случаев. Так, например "таблица-лог" с большими сообщениями не будет нормально сжиматься ни rows, ни page, зато может в десяток раз сжаться в бэкапе. Таблица с большим количеством низкоселективных ссылочных полей будет отлично жаться в page, зато потом плохо в бэкапе. А может для конкретно случая лучше подойдёт columnstore.

Так что всё равно придётся смотреть по месту, экспериментировать и замерять.