¿Una forma alternativa de comprimir NVARCHAR (MAX)?

14

Estoy tratando de comprimir algunas tablas que tienen NVARCHAR(MAX)campos. Por desgracia, el rowy la pagecompresión no tienen el impacto deseo (sólo ~ 100/200 MB guarda para 20 GB de mesa). Además, no puedo aplicar compresiones de archivo de almacén de columna y de almacén de columna porque no admiten la compresión de NVARCHAR(MAX)campos.

¿Alguien puede saber si tengo alguna alternativa aquí?

También supongo que la compresión rowy pageno tienen efecto porque el contenido de las NVARCHAR(MAX)columnas es único.

gotqn
fuente
2
¿Los valores de las columnas son definitivamente más anchos que 8000 caracteres? por ejemplo, SELECT MAX (CAST (LEN (widecolumn) AS BIGINT)) FROM dbo.largeTable De lo contrario, podría convertirlos en varchar ordinario y aplicar el almacén de columnas en clúster.
wBob
@wBob Incluso si el valor más grande fuera solo de 2000 caracteres, ¿no se convertiría en una VARCHARposible pérdida de datos si se utilizan caracteres de más de 1 página de códigos? Creo que el consejo debería ser convertir a NVARCHAR(4000)si la longitud máxima no es mayor a 4000 porque entonces todos los valores serían elegibles para la compresión Unicode completa. Aún así, probablemente sea seguro suponer a partir de la información en la Pregunta que los valores tienen más de 4000 caracteres, por lo que actualmente no se están comprimiendo.
Solomon Rutzky

Respuestas:

16

La compresión de páginas y filas no comprime BLOB .

Debido a su tamaño, los tipos de datos de gran valor a veces se almacenan por separado de los datos de fila normales en páginas de propósito especial. La compresión de datos no está disponible para los datos que se almacenan por separado.

Si desea comprimir BLOB, debe almacenarlos VARBINARY(MAX)y aplicar el algoritmo de compresión de flujo que prefiera. Por ejemplo GZipStream. Hay muchos ejemplos de cómo hacer esto, solo busque GZipStream y SQLCLR.

Remus Rusanu
fuente
10

Hay (ahora) potencialmente dos formas de lograr una compresión personalizada:

  1. A partir de SQL Server 2016, hay funciones integradas para COMPRESS y DECOMPRESS . Estas funciones usan el algoritmo GZip.

  2. Use SQLCLR para implementar cualquier algoritmo que elija (como @Remus mencionó en su respuesta). Esta opción está disponible en versiones anteriores a SQL Server 2016, desde SQL Server 2005.

    GZip es una opción fácil porque está disponible dentro de .NET y en las bibliotecas compatibles de .NET Framework (el código puede estar en un SAFEensamblado). O, si desea GZip pero no quiere ocuparse de codificarlo / implementarlo, puede usar las funciones Util_GZip y Util_GUnzip que están disponibles en la versión gratuita de la biblioteca SQL # SQLCLR (de la que soy autor).

    Si decide usar GZip, ya sea que lo codifique usted mismo o use SQL #, tenga en cuenta que el algoritmo utilizado en .NET para hacer la compresión GZip cambió en Framework versión 4.5 para mejor (consulte la sección "Comentarios" en el MSDN página para la clase GZipStream ). Esto significa:

    1. Si está utilizando SQL Server 2005, 2008 o 2008 R2, todos vinculados a CLR v 2.0 que maneja las versiones de Framework 2.0, 3.0 y 3.5, entonces el cambio realizado en la versión 4.5 de Framework no tiene efecto y desafortunadamente está atascado con Algoritmo original y desagradable de .NET.
    2. Si está utilizando SQL Server 2012 o más reciente (hasta ahora 2014 y 2016), todos vinculados a CLR v 4.0 que maneja las versiones de Framework 4.0, 4.5.x, 4.6, puede usar el algoritmo más nuevo y mejor. El único requisito es que haya actualizado .NET Framework en el servidor que ejecuta SQL Server para que sea la versión 4.5 o posterior.

    Sin embargo, no tiene que usar GZip y es libre de implementar cualquier algoritmo como.

TENGA EN CUENTA: todos los métodos mencionados anteriormente son más "soluciones" en lugar de ser reemplazos reales, a pesar de que técnicamente son "formas alternativas de comprimir datos NVARCHAR (MAX)". La diferencia es que con la compresión de datos incorporada rowy pageofrecida por SQL Server, la compresión se maneja detrás de escena y los datos aún son utilizables, legibles e indexables. Pero comprimir cualquier dato en un VARBINARYmedio significa que está ahorrando espacio, pero renunciando a alguna funcionalidad. Es cierto que una cadena de 20k no es indexable de todos modos, pero aún se puede usar en unWHEREcláusula, o con cualquier función de cadena. Para hacer cualquier cosa con un valor comprimido personalizado, necesitaría descomprimirlo sobre la marcha. Al comprimir archivos binarios (PDF, JPEG, etc.) esto no es un problema, pero esta pregunta era específica de los NVARCHARdatos.

Solomon Rutzky
fuente