Eu criei uma tabela com 650 colunas Numeric(19,4). Quando ligo a compactação de página, executando
ALTER TABLE fct.MyTable REBUILD WITH (DATA_COMPRESSION = PAGE);
eu recebo
Msg 1975, Level 16, State 1
Index O comprimento da linha 'PK_Mytable' excede o comprimento máximo permitido de '8060' bytes.
mas 650 vezes 9 bytes são apenas 5850 bytes, o que está bem longe do limite declarado de 8060 bytes.
O servidor está executando o Windows 2012 r2 com SQL Server 2016 SP1 CU2
Qual é a sobrecarga de linha ao usar a compactação de página?
Aqui está algum código para mostrar o que quero dizer:
/* 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
A compactação de linhas também falha, mas em uma contagem de linhas diferente.
Se você tentar criar sua tabela sem a restrição de PK clusterizada, receberá um erro um pouco diferente:
Nesta mensagem de erro, você pode ver que há 1530 bytes de sobrecarga interna para compactação de página.
Agora você pode fazer as contas:
bigint
MyTableIDint
LastColumnnumeric(19,4)
colunas (total de 5337 bytes)Então, 8 + 4 + (593*9) + 1530 = 6879. Espere um segundo... Isso ainda está abaixo de 8060. O que há com isso?!
O algoritmo de compactação de página, na verdade, empilha vários algoritmos de compactação juntos. O primeiro passo é aplicar a compressão ROW. A sobrecarga de compactação de linha não está incluída nos 1530 bytes de sobrecarga listados nessa mensagem de erro.
Você pode ler mais sobre como a compactação de linhas funciona aqui no meu blog e aqui no BOL . Você notará no artigo BOL que ele descreve o
numeric
armazenamento como "Este armazenamento é exatamente o mesmo que o formato de armazenamento vardecimal", mas não explicavardecimal
. Este post cobrevardecimal
um pouco mais - essencialmente, ele adiciona 2 bytes de sobrecarga por coluna para armazenar o comprimento real (semelhante ao quevarchar
faz).A compactação de linha exigirá 2 bytes adicionais para cada uma das 593
numeric
colunas, mais obigint
eint
exigirá 1 byte de sobrecarga cada.Os requisitos de armazenamento compactado por linha seriam:
bigint
MyTableIDint
LastColumnnumeric(19,4)
colunas8 + 4 + (593*9) = 5349 bytes de dados
1 + 1 + (593*2) = sobrecarga de compactação de linha de 1188 bytes
Total de 6.537 bytes para esquema compactado por linha
Agora que temos o tamanho da linha para o esquema compactado por linha, podemos revisitar nossa matemática. O tamanho da linha compactada de página será o tamanho dos dados + sobrecarga de compactação de linha + sobrecarga de compactação de página:
bigint
MyTableIDint
LastColumnnumeric(19,4)
colunastotal de 8067 bytes