Qual è l'overhead di riga quando si utilizza Compressione pagine?


10

Ho creato una tabella con 650 colonne numeriche (19,4). Quando accendo Page Compression, eseguendo

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

ottengo

Messaggio 1975, livello 16, stato 1
La lunghezza della riga dell'indice "PK_Mytable" supera la lunghezza massima consentita di "8060" byte.

ma 650 volte 9 byte sono solo 5850 byte, che è abbastanza lontano dal limite dichiarato di 8060 byte.

Il server esegue Windows 2012 R2 con SQL Server 2016 SP1 CU2

Qual è l'overhead di riga quando si utilizza Compressione pagine?

Ecco un po 'di codice per mostrare cosa intendo:

/* 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

Anche la compressione delle righe ha esito negativo, ma con un conteggio delle righe diverso.


Quanto è grande la tua chiave primaria? Se questa è una tabella dei fatti e vuoi comprimere e migliorare le prestazioni, ti suggerisco di leggere su indici columnstore, possono avere un impatto notevole. Il sovraccarico della compressione della pagina è un maggiore utilizzo della CPU per la decompressione.
Stijn Wynants,

@StijnWynants; 8 byte viene utilizzato per BigInts. Questo è davvero un dato di fatto, ma non ci sono abbastanza righe in arrivo per giustificare un indice columnstore.
Henrik Staun Poulsen,

Risposte:


13

Se provi a creare la tua tabella senza il vincolo PK in cluster e otterrai un errore leggermente diverso:

Messaggio 1701, livello 16, stato 1, riga 1 Creazione o modifica della tabella "Mytable" non riuscita perché la dimensione minima della riga sarebbe 8067, inclusi 1530 byte di overhead interno. Questo supera la dimensione massima consentita della riga della tabella di 8060 byte.

In questo messaggio di errore, puoi vedere che ci sono 1530 byte di sovraccarico interno per la compressione della pagina.

Ora puoi fare i conti:

  • 8 byte per bigintMyTableID
  • 4 byte per intLastColumn
  • 9 byte per ciascuna delle 593 numeric(19,4)colonne (5337 byte totali)
  • 1530 byte di sovraccarico di compressione

Quindi, 8 + 4 + (593 * 9) + 1530 = 6879. Aspetta un secondo .... È ancora inferiore a 8060. Che succede ?!


L'algoritmo di compressione della pagina raggruppa effettivamente diversi algoritmi di compressione. Il primo passo è applicare la compressione ROW. Il sovraccarico della compressione delle righe non è incluso nei 1530 byte del sovraccarico elencati in quel messaggio di errore.

Puoi leggere di più su come funziona la compressione delle righe qui sul mio blog e qui in BOL . Noterai nell'articolo BOL che descrive lo numericspazio di archiviazione come "Questo spazio di archiviazione è esattamente uguale al formato di archiviazione vardecimale", ma non spiega vardecimal. Questo post copre vardecimalun po 'di più - essenzialmente, aggiunge 2 byte di overhead per colonna per memorizzare la lunghezza effettiva (simile a ciò che varcharfa).

La compressione delle numericrighe richiederà altri 2 byte per ciascuna delle 593 colonne, più biginte intrichiederà 1 byte di sovraccarico ciascuna.

I requisiti di archiviazione compressi per riga sarebbero:

  • 8 byte + 1 byte di overhead per bigintMyTableID
  • 4 byte + 1 byte di sovraccarico per intLastColumn
  • 9 byte + 2 byte di sovraccarico per ciascuna delle 593 numeric(19,4)colonne
  • 1188 byte di sovraccarico di compressione ROW

8 + 4 + (593 * 9) = 5349 byte di dati

1 + 1 + (593 * 2) = 1188 byte sovraccarico di compressione delle righe

6537 byte totali per lo schema compresso riga


Ora che abbiamo le dimensioni della riga per lo schema compresso per riga, possiamo rivisitare la nostra matematica. La dimensione della riga compressa nella pagina sarà la dimensione dei dati + sovraccarico della compressione della riga + sovraccarico della compressione della pagina:

  • 8 byte per bigintMyTableID
  • 4 byte per intLastColumn
  • 9 byte per ciascuna delle 593 numeric(19,4)colonne
  • 1188 byte di sovraccarico di compressione ROW
  • 1530 byte di sovraccarico di compressione PAGE
  5349 byte di dati 
+ 1188 byte sovraccarico di compressione delle righe 
+ 1530 byte sovraccarico di compressione della pagina 

8067 byte totali


1
Mi piace la tua conclusione: "Nella maggior parte dei casi, scoprirai che la compressione delle righe è in grado di risparmiare spazio, ma non sempre". 2718 byte di overhead sono molto più di quanto mi aspettassi. Grazie mille per aver dedicato del tempo a scrivere una risposta così dettagliata.
Henrik Staun Poulsen,

1
@HenrikStaunPoulsen Un'altra cosa importante da ricordare è che SQL Server deve presumere che i dati potrebbero non essere compressi. Pertanto, anche se i dati vengono compressi a meno di 8060 byte, SQL Server deve eseguire i calcoli della dimensione della riga in base alla dimensione massima teorica della riga per i dati non comprimibili.
Due

Dopo 3 giorni, sono ancora sorpreso dal numero di byte richiesti per la compressione Row; 2 byte per colonna. La compressione della pagina aggiunge quasi 3 byte. Ma; grazie per l'aiuto. È stato molto utile
Henrik Staun Poulsen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.