Я создал таблицу с 650 числовыми (19,4) столбцами. Когда я включаю Page Compression, запустив
ALTER TABLE fct.MyTable REBUILD WITH (DATA_COMPRESSION = PAGE);
я получил
Сообщение 1975, уровень 16, состояние 1
Индекс Длина строки PK_Mytable превышает максимально допустимую длину в 8060 байтов.
но 650 умножить на 9 байтов - это только 5850 байтов, что довольно далеко от заявленного предела в 8060 байтов.
Сервер работает под управлением Windows 2012 r2 с SQL Server 2016 SP1 CU2
Каковы издержки строки при использовании сжатия страницы?
Вот некоторый код, чтобы показать, что я имею в виду:
/* test script to demo MSG 1975 */
DECLARE @sql NVARCHAR(max)='', @i INT =0
drop table if exists dbo.mytable;
SET @sql = 'Create table dbo.Mytable (MyTableID bigint not null
identity(1,1) primary key clustered, '
WHILE @i < 593 BEGIN
SET @sql += ' Column' + LTRIM(@i) + ' numeric(19,4) null, '
SET @i +=1
END
SET @sql += ' LastColumn int) '
--SET @sql += ' with (DATA_COMPRESSION = ROW) '
SET @sql += ' with (DATA_COMPRESSION = PAGE) '
SELECT @sql
EXEC sys.sp_executesql @sql
SELECT top 10000 * FROM dbo.MyTable MT
Сжатие строк также не выполняется, но при другом количестве строк.
sql-server-2016
compression
data-pages
Хенрик Стаун Поулсен
источник
источник
Ответы:
Если вы попытаетесь создать свою таблицу без кластерного ограничения PK, и вы получите немного другую ошибку:
В этом сообщении об ошибке вы можете увидеть, что для сжатия страниц существует 1530 байт внутренних издержек.
Теперь вы можете сделать математику:
bigint
MyTableIDint
LastColumnnumeric(19,4)
столбцов (всего 5337 байтов)Итак, 8 + 4 + (593 * 9) + 1530 = 6879. Подождите секунду ... Это все еще ниже 8060. Что с этим ?!
Алгоритм сжатия страниц фактически объединяет несколько алгоритмов сжатия. Первый шаг - применить сжатие ROW. Накладные расходы на сжатие строк не включаются в 1530 байтов служебных данных, перечисленных в этом сообщении об ошибке.
Вы можете узнать больше о том, как работает сжатие строк, здесь, в моем блоге и здесь, в BOL . В статье BOL вы заметите, что она описывает
numeric
хранилище как «Это хранилище точно такое же, как формат хранения vardecimal», но не объясняетvardecimal
. Этот пост охватываетvardecimal
немного больше - по сути, он добавляет 2 байта служебной информации на столбец для хранения фактической длины (аналогично тому, чтоvarchar
делает).Сжатие строки потребует дополнительных 2 байтов для каждого из 593
numeric
столбцов, а такжеbigint
иint
потребуется 1 байт служебной информации каждый.В строках сжатых требований к хранению будут:
bigint
MyTableIDint
LastColumnnumeric(19,4)
столбцов8 + 4 + (593 * 9) = 5349 байт данных
1 + 1 + (593 * 2) = 1188 байт для сжатия строки
Всего 6537 байт для схемы со сжатием строк
Теперь, когда у нас есть размер строки для схемы со сжатием строк, мы можем вернуться к нашей математике. Размер строки со сжатием страницы будет равен размеру данных + накладные расходы на сжатие строк + накладные расходы на сжатие страниц:
bigint
MyTableIDint
LastColumnnumeric(19,4)
столбцовВсего 8067 байт
источник