我已经为压缩/解压缩NVARCHAR列创建了一个简单的CLR函数:
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
public static SqlBinary Compress( string str ){
if( str == null ){return new SqlBinary();}
if( String.IsNullOrEmpty( str ) ){str = " ";}
byte[] bytes = Encoding.Unicode.GetBytes( str );
using( MemoryStream msi = new MemoryStream( bytes ) ){
using( MemoryStream mso = new MemoryStream() ){
using( GZipStream gs = new GZipStream( mso, CompressionMode.Compress ) ){
msi.CopyTo( gs );
}
return new SqlBinary( mso.ToArray() );
}
}
}我得到的压缩比大约是4,或者如果我有1024 KB的非压缩数据,我将得到256 KB的压缩数据。我知道这个比率取决于数据本身及其大小,但我想得到一个更好的比率。
由于我使用的是Server 2012和.net 4.0,是否由于这之类的问题,压缩没有给出预期的比率?
我是否可以在SQL函数中使用另一个类?有这类替代办法,但目前不支持。
发布于 2015-01-16 07:01:49
以下是一些有关这方面的想法:
CompressionMode.Compress更改为CompressionLevel.Optimal即可。Server绑定到CLR的特定版本,而不是绑定到特定版本的.NET框架。这意味着,任何受支持的库中的任何新功能都是可用的,只要您将代码部署到的任何服务器已经更新了它的.NET。这并不意味着您将得到更好的压缩。我测试了这段代码,它生成了与PHP和Fiddler生成的"Hello“相同的31个字节,正如您链接到的一个问题:https://stackoverflow.com/questions/11435200/why-does-my-c-sharp-gzip-produce-a-larger-file-than-fiddler-or-php中所指出的那样。我刚刚用3405个随机字符(即"fsdkjf .“)进行了再次测试。我将变量声明为NVARCHAR(4000),并在进行了我在这里建议的更改之后,在代码中运行它。压缩二进制文件的长度为211字节。然后,我将相同的字符串复制并粘贴到Notepad++中,确保编码设置为"UCS-2 Little Endian“并保存。我在Windows Explorer中检查了该文件,它是6812字节(数据中的6810字节,正如变量的DATALENGTH所报告的那样,加上字节顺序标记的2字节)。我以二进制模式将其发送到Linux服务器。Linux服务器上的文件大小仍然是6812。然后我对其运行gzip -9 (即最大压缩;默认为-6)。压缩大小? 231字节。因此,.NET GZipStream实际上做得稍微好一些。CompressionMode.Compress和CompressionLevel.Optimal在功能上等价。在指定对方时,每一个都是假定的默认值。string;使用SqlString。byte[] bytes行new MemoryStream( bytes )块中的using更改为: new MemoryStream(str.GetUnicodeBytes())if( str == null ){return new SqlBinary();}行。不要在.NET代码中处理这个问题,只需将WITH RETURNS NULL ON NULL INPUT添加到创建功能中即可。这样,如果输入为NULL :),Server甚至不会调用您的代码。请记住,当您有多个输入参数时,如果其中任何一个参数为NULL,则此选项将返回NULL。如果它们中至少有一个能够传递NULL,那么您就必须在代码中处理这种情况。if( String.IsNullOrEmpty( str ) ){str = " ";}替换为: if (str.Value.Length == 0) {返回SqlBinary.Null;}https://dba.stackexchange.com/questions/89362
复制相似问题