¿Cuál es la sobrecarga de la fila cuando se usa la compresión de página?


10

He creado una tabla con 650 columnas numéricas (19,4). Cuando enciendo la compresión de página, al ejecutar

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

yo obtengo

Msg 1975, Nivel 16,
Índice de estado 1 La longitud de la fila 'PK_Mytable' excede la longitud máxima permitida de '8060' bytes.

pero 650 veces 9 bytes es solo 5850 bytes, lo cual está bastante lejos del límite establecido de 8060 bytes.

El servidor ejecuta Windows 2012 r2 con SQL Server 2016 SP1 CU2

¿Cuál es la sobrecarga de la fila cuando se usa la compresión de página?

Aquí hay un código para mostrar lo que quiero decir:

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

La compresión de filas también falla, pero en un recuento de filas diferente.


¿Qué tan grande es tu clave principal? Si se trata de una tabla de hechos y desea comprimir y mejorar el rendimiento, le sugiero que lea los índices del almacén de columnas, ya que pueden tener un gran impacto. Sobrecarga de la página de compresión es más uso de CPU para descomprimir.
Stijn Wynants

@StijnWynants; 8 bytes se utilizan para BigInts. Esto es un hecho, pero no hay suficientes filas entrantes para garantizar un índice de almacén de columnas.
Henrik Staun Poulsen

Respuestas:


13

Si intenta crear su tabla sin la restricción PK agrupada, obtendrá un error ligeramente diferente:

Msg 1701, Nivel 16, Estado 1, Línea 1 Error al crear o modificar la tabla 'Mytable' porque el tamaño mínimo de fila sería 8067, incluidos 1530 bytes de sobrecarga interna. Esto excede el tamaño máximo de fila de tabla permitido de 8060 bytes.

En este mensaje de error, puede ver que hay 1530 bytes de sobrecarga interna para la compresión de la página.

Ahora, puedes hacer los cálculos:

  • 8 bytes para bigintMyTableID
  • 4 bytes para intLastColumn
  • 9 bytes para cada una de las 593 numeric(19,4)columnas (5337 bytes en total)
  • 1530 bytes de sobrecarga de compresión

Entonces, 8 + 4 + (593 * 9) + 1530 = 6879. Espera un segundo ... Eso todavía está por debajo de 8060. ¿Qué pasa con eso?


El algoritmo de compresión de página en realidad apila varios algoritmos de compresión juntos. El primer paso es aplicar compresión ROW. La sobrecarga de la compresión de filas no se incluye en los 1530 bytes de sobrecarga enumerados en ese mensaje de error.

Puede leer más sobre cómo funciona la compresión de filas aquí en mi blog y aquí en BOL . numericNotarás en el artículo de BOL que describe el almacenamiento como "Este almacenamiento es exactamente el mismo que el formato de almacenamiento vardecimal", pero no explica vardecimal. Esta publicación cubre vardecimalun poco más, esencialmente, agrega 2 bytes de sobrecarga por columna para almacenar la longitud real (similar a lo que varcharhace).

La compresión de filas requerirá 2 bytes adicionales para cada una de las 593 numericcolumnas, más biginty intrequerirá 1 byte de sobrecarga cada una.

Los requisitos de almacenamiento comprimido por filas serían:

  • 8 bytes + 1 byte de gastos generales para bigintMyTableID
  • intSobrecarga de 4 bytes + 1 byte para LastColumn
  • 9 bytes + 2 bytes de sobrecarga para cada una de las 593 numeric(19,4)columnas
  • 1188 bytes de sobrecarga de compresión ROW

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

1 + 1 + (593 * 2) = sobrecarga de compresión de fila de 1188 bytes

6537 bytes en total para el esquema comprimido por filas


Ahora que tenemos el tamaño de fila para el esquema comprimido de fila, podemos volver a ver nuestras matemáticas. El tamaño de fila comprimido por página será el tamaño de datos + sobrecarga de compresión de fila + sobrecarga de compresión de página:

  • 8 bytes para bigintMyTableID
  • 4 bytes para intLastColumn
  • 9 bytes para cada una de las 593 numeric(19,4)columnas
  • 1188 bytes de sobrecarga de compresión ROW
  • 1530 bytes de sobrecarga de compresión PAGE
  5349 bytes de datos 
Sobrecarga de compresión de fila de + 1188 bytes 
Sobrecarga de compresión de página de + 1530 bytes 

8067 bytes en total


1
Me gusta su conclusión: "En la mayoría de los casos, encontrará que la compresión de filas puede ahorrar algo de espacio, pero no siempre". 2718 bytes de sobrecarga es mucho más de lo que esperaba. Muchas gracias por tomarse el tiempo para escribir una respuesta tan detallada.
Henrik Staun Poulsen

1
@HenrikStaunPoulsen Una cosa importante adicional para recordar es que SQL Server debe asumir que sus datos podrían no ser comprimidos. Por lo tanto, incluso si sus datos se comprimen a menos de 8060 bytes, SQL Server debe realizar los cálculos de tamaño de fila en función del tamaño de fila máximo teórico para datos no comprimibles.
AMtwo

Después de 3 días, todavía me sorprende la cantidad de bytes necesarios para la compresión de filas; 2 bytes por columna. La compresión de página agrega casi 3 bytes además de eso. Pero; Gracias por tu ayuda. Fue de lo más útil.
Henrik Staun Poulsen
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.