Qual é a sobrecarga da linha ao usar a compactação de página?

10

Eu criei uma tabela com 650 colunas numéricas (19,4). Quando ligo a compactação de página, executando

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

eu recebo

Mensagem 1975, Nível 16, Estado 1
O comprimento da linha do índice 'PK_Mytable' excede o comprimento máximo permitido de bytes '8060'.

mas 650 vezes 9 bytes são apenas 5850 bytes, o que está muito longe do limite declarado de 8060 bytes.

O servidor está executando o Windows 2012 r2 com o SQL Server 2016 SP1 CU2

Qual é a sobrecarga da linha ao usar a compactação de página?

Aqui está um 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 linha também falha, mas com uma contagem de linhas diferente.

Henrik Staun Poulsen
fonte
Qual é o tamanho da sua chave primária? Se essa é uma tabela de fatos e você deseja compactar e aprimorar o desempenho, sugiro que você leia os índices columnstore, eles podem causar bastante impacto. A sobrecarga da compactação de página é mais uso da CPU para descompactar.
Stijn Wynants
@StijnWynants; 8 bytes são usados ​​para BigInts. Isso é realmente um fato, mas não há linhas suficientes chegando para garantir um índice columnstore.
Henrik Staun Poulsen

Respostas:

13

Se você tentar criar sua tabela sem a restrição PK em cluster e obterá um erro ligeiramente diferente:

Msg 1701, Nível 16, Estado 1, Linha 1 A criação ou alteração da tabela 'Mytable' falhou porque o tamanho mínimo da linha seria 8067, incluindo 1530 bytes de sobrecarga interna. Isso excede o tamanho máximo permitido da linha da tabela de 8060 bytes.

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:

  • 8 bytes para bigintMyTableID
  • 4 bytes para intLastColumn
  • 9 bytes para cada uma das 593 numeric(19,4)colunas (5337 bytes no total)
  • 1530 bytes de sobrecarga de compactação

Então, 8 + 4 + (593 * 9) + 1530 = 6879. Espere um segundo ... Ainda está abaixo de 8060. O que há com isso ?!


O algoritmo de compactação de página realmente empilha vários algoritmos de compactação juntos. O primeiro passo é aplicar a compressão ROW. A sobrecarga da 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ê observará no artigo da BOL que descreve o numericarmazenamento como "Este armazenamento é exatamente igual ao formato de armazenamento vardecimal", mas não explica vardecimal. Este post aborda vardecimalum pouco mais - essencialmente, ele adiciona 2 bytes de sobrecarga por coluna para armazenar o comprimento real (semelhante ao que varcharfaz).

A compactação de linha exigirá 2 bytes adicionais para cada uma das 593 numericcolunas, mais o biginte intexigirá 1 byte de sobrecarga cada.

Os requisitos de armazenamento compactado em linha seriam:

  • 8 bytes + sobrecarga de 1 byte para bigintMyTableID
  • Sobrecarga de 4 bytes + 1 byte para intLastColumn
  • Sobrecarga de 9 bytes + 2 bytes para cada uma das 593 numeric(19,4)colunas
  • 1188 bytes de sobrecarga de compactação ROW

8 + 4 + (593 * 9) = 5349 bytes de dados

1 + 1 + (593 * 2) = 1188 bytes de sobrecarga de compactação de linha

6537 bytes no total para esquema compactado em linha


Agora que temos o tamanho da linha para o esquema compactado, podemos revisar nossa matemática. O tamanho da linha compactada na página será o tamanho dos dados + sobrecarga de compactação de linha + sobrecarga de compactação de página:

  • 8 bytes para bigintMyTableID
  • 4 bytes para intLastColumn
  • 9 bytes para cada uma das 593 numeric(19,4)colunas
  • 1188 bytes de sobrecarga de compactação ROW
  • 1530 bytes de sobrecarga de compactação PAGE
  Dados de 5349 bytes 
Sobrecarga de compactação de linha de + 1188 bytes 
+ 1530 bytes de sobrecarga de compactação de página 

8067 bytes no total

AMtwo
fonte
11
Gosto da sua conclusão: "Na maioria dos casos, você verá que a compactação de linhas é capaz de economizar espaço - mas nem sempre". 2718 bytes de sobrecarga são muito mais do que eu esperava. Muito obrigado por reservar um tempo para escrever uma resposta tão detalhada.
Henrik Staun Poulsen
11
@HenrikStaunPoulsen Outra coisa importante a lembrar é que o SQL Server precisa assumir que seus dados podem não ser compactados. Portanto, mesmo que seus dados sejam compactados para menos de 8060 bytes, o SQL Server deve fazer os cálculos de tamanho de linha com base no tamanho máximo teórico de linha para dados não compactáveis.
AMtwo
Após três dias, ainda estou impressionado com o número de bytes necessários para a compactação de linhas; 2 bytes por coluna. A compactação de página adiciona quase 3 bytes além disso. Mas; obrigado pela ajuda. Foi muito útil.
Henrik Staun Poulsen