Що таке накладні рядки при використанні стиснення сторінки?


10

Я створив таблицю з 650 числовими (19,4) стовпцями. Коли я вмикаю Стиснення сторінки, запустивши

ALTER TABLE fct.MyTable REBUILD  WITH (DATA_COMPRESSION = PAGE);

я отримав

Msg 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

Стиснення рядків також не вдається, але при різному підрахунку рядків.


Наскільки великий ваш основний ключ? Якщо це таблиця фактів, і ви хочете стиснути та підвищити продуктивність, я пропоную вам прочитати на індексах стовпців, вони можуть зробити неабиякий вплив. Накладні стиснення сторінки - це більше використання процесора для декомпресії.
Stijn Wynants

@StijnWynants; 8 байт використовується для BigInts. Це насправді факт, але не існує достатньо рядків, щоб підтвердити індекс магазину стовпців.
Генрік Стаун Поульсен

Відповіді:


13

Якщо ви спробуєте створити свою таблицю без кластерного обмеження ПК, ви отримаєте дещо іншу помилку:

Msg 1701, рівень 16, стан 1, рядок 1 Створення або зміни таблиці "Mytable" не вдалося, оскільки мінімальний розмір рядка складе 8067, включаючи 1530 байт внутрішніх накладних даних. Це перевищує максимально допустимий розмір рядка таблиці 8060 байт.

У цьому повідомленні про помилку ви бачите, що для стиснення сторінки є 1530 байт внутрішніх накладних витрат.

Тепер ви можете займатися математикою:

  • 8 байт для bigintMyTableID
  • 4 байти для intLastColumn
  • 9 байт для кожного з 593 numeric(19,4)стовпців (всього 5337 байт)
  • 1530 байт стиснення накладних витрат

Отже, 8 + 4 + (593 * 9) + 1530 = 6879. Почекайте секунду .... Це ще нижче 8060. Що з цим ?!


Алгоритм стиснення сторінки фактично складає кілька алгоритмів стиснення разом. Перший крок - застосувати стиснення ROW. Накладні витрати на стиснення рядків не включаються в 1530 байт накладних даних, перелічених у цьому повідомленні про помилку.

Ви можете прочитати більше про те, як працює стиснення рядків тут, у моєму блозі та тут, у BOL . У статті BOL ви зазначите, що він описує numericсховище як "Цей сховище точно такий же, як і формат зберігання вардецимального", але не пояснює vardecimal. Ця публікація охоплює vardecimalтрохи більше - по суті, вона додає 2 байти накладних витрат на стовпець, щоб зберігати фактичну довжину (аналогічно тому, що varcharробить).

Для стиснення рядків потрібно буде додатково 2 байти для кожного з 593 numericстовпців, плюс bigintі intбуде потрібно 1 байт накладних даних у кожному.

Вимоги до пам’яті стиснених рядків будуть:

  • 8 байт + 1 байт накладних витрат для bigintMyTableID
  • 4 байти + 1 байт накладних витрат для intLastColumn
  • 9 байт + 2 байти накладних даних для кожного з 593 numeric(19,4)стовпців
  • 1188 байт скорочення стиснення ROW

8 + 4 + (593 * 9) = 5349 байт даних

1 + 1 + (593 * 2) = 1188 байт стискання рядкових накладних витрат

Загальна кількість 6537 байт для схеми, стиснутої рядками


Тепер, коли у нас є розмір рядка для стиснутої рядком схеми, ми можемо переглянути нашу математику. Розмір рядка, стисненого сторінкою, буде розміром даних + накладні витрати на стиснення рядків + накладні витрати на стиснення сторінки:

  • 8 байт для bigintMyTableID
  • 4 байти для intLastColumn
  • 9 байт для кожного з 593 numeric(19,4)стовпців
  • 1188 байт скорочення стиснення ROW
  • 1530 байт PAGE стиснення накладних витрат
  5349 байт даних 
+ 1188 байт стискання рядкових накладних витрат 
+ 1530 байт сторінки стиснення накладних витрат 

8067 байт усього


1
Мені подобається ваш висновок: "У більшості випадків ви виявите, що стиснення рядків може заощадити простір - але не завжди". 2718 байт накладних витрат набагато більше, ніж я очікував. Дуже дякую, що знайшли час, щоб написати таку детальну відповідь.
Генрік Стаун Поульсен

1
@HenrikStaunPoulsen Додатковим важливим, що потрібно пам’ятати, є те, що SQL Server повинен вважати, що ваші дані можуть бути неможливо стиснути. Тож навіть якщо ваші дані стискатимуться до менш ніж 8060 байт, SQL Server повинен здійснити обчислення розміру рядків на основі теоретичного максимального розміру рядків для некомпресивних даних.
AMtwo

Через 3 дні я все ще вражений кількістю байтів, необхідних для стиснення рядків; 2 байти на стовпчик. Стиснення сторінки додає майже 3 байти поверх цього. Але; Дякую за твою допомогу. Це було найкорисніше.
Генрік Стаун Поульсен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.