压缩NVARCHAR(MAX)的另一种方法?


14

我正在尝试压缩一些具有NVARCHAR(MAX)字段的表。不幸的是,rowpage压缩并没有产生预期的影响(对于20 GB的表仅节省了约100/200 MB)。另外,我无法应用列存储和列存储档案压缩,因为它们不支持NVARCHAR(MAX)字段压缩。

有人可以告诉我在这里是否有其他选择吗?

我也猜想rowpage压缩没有效果,因为NVARCHAR(MAX)列的内容是唯一的。


2
列值是否肯定大于8000个字符?例如,从dbo.largeTable中选择SELECT MAX(CAST(LEN(widecolumn)AS BIGINT)))否则,您可以将它们转换为普通的varchar并应用集群列存储。
wBob 2014年

@wBob即使最大值只有2000个字符,VARCHAR如果使用的字符数超过1个代码页,是否还会转换成潜在的数据丢失?我认为建议是将NVARCHAR(4000)最大长度不大于4000 转换为,因为这样所有值都可以进行完整的Unicode压缩。不过,从“问题”中的信息来看,可以安全地假设这些值已超过4000个字符,这就是为什么它们当前未压缩的原因。
所罗门·鲁茨基

Answers:


16

页面压缩和行压缩都不压缩BLOB

由于它们的大小,大数值数据类型有时与常规行数据分开存储在特殊目的页面上。数据压缩不适用于单独存储的数据。

如果要压缩BLOB,则需要将它们存储为VARBINARY(MAX)并应用您选择的流压缩算法。例如GZipStream。有许多示例如何执行此操作,仅搜索GZipStream和SQLCLR。


10

(现在)可能有两种方法可以完成自定义压缩:

  1. 从SQL Server 2016开始,内置了COMPRESSDECOMPRESS的功能。这些函数使用GZip算法。

  2. 使用SQLCLR来实现您选择的任何算法(如他的答案中提到的@Remus)。此选项在SQL Server 2016之前的版本中可用,一直追溯到SQL Server 2005。

    GZip是一个简单的选择,因为它可以在.NET 受支持的.NET Framework库中找到(代码可以在SAFEAssembly中)。或者,如果您想要GZip但不想处理编码/部署,则可以使用SQL# SQLCLR库的免费版本(我是作者)中提供的Util_GZipUtil_GUnzip函数。

    如果您决定使用GZip,无论是自己编写代码还是使用SQL#,请注意,在.NET中用于进行GZip压缩的算法最好在Framework 4.5版中进行了更改(请参见MSDN上的“备注”部分)GZipStream类的页面)。这表示:

    1. 如果您使用的是SQL Server 2005、2008或2008 R2(均链接到处理Framework 2.0、3.0和3.5的CLR v 2.0),那么在Framework 4.5中所做的更改将无效,并且您很遗憾地坚持使用.NET的原始算法。
    2. 如果您使用的是SQL Server 2012或更高版本(截至2014年和2016年)(均链接到处理Framework 4.0、4.5.x,4.6版本的CLR v 4.0),则可以使用更新更好的算法。唯一的要求是,您已将运行SQL Server的服务器上的.NET Framework更新为4.5或更高版本。

    但是,您不必使用GZip,也可以自由实现任何类似算法。

请注意:上面提到的所有方法都是“变通方法”,而不是实际替代方法,即使它们在技术上是“压缩NVARCHAR(MAX)的替代方法”数据。区别在于,使用SQL Server提供的内置数据压缩(row和)page,压缩是在后台进行的,并且数据仍然可用,可读和可索引。但是将任何数据压缩成某种形式VARBINARY意味着您可以节省空间,但是却放弃了一些功能。没错,一个20k的字符串无论如何都无法索引,但仍可以在WHERE子句或任何字符串函数。为了使用自定义压缩值执行任何操作,您需要即时对其进行解压缩。压缩二进制文件(PDF,JPEG等)时,这不是问题,但是此问题仅针对NVARCHAR数据。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.