首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GZipStream/DeflateStream压缩方案

GZipStream/DeflateStream压缩方案
EN

Database Administration用户
提问于 2015-01-15 12:20:41
回答 1查看 2.9K关注 0票数 6

我已经为压缩/解压缩NVARCHAR列创建了一个简单的CLR函数:

代码语言:javascript
复制
[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函数中使用另一个类?有这类替代办法,但目前不支持。

EN

回答 1

Database Administration用户

回答已采纳

发布于 2015-01-16 07:01:49

以下是一些有关这方面的想法:

  1. 您知道您应该对您测试过的字符串进行更好的压缩吗?您是否通过.NET之外的Have测试过这些相同的字符串?例如在Linux / CygWin上-- UNIX实用程序的DOS端口/ PHP /等?
  2. 如果您已经用.NET 4.5更新了您的系统,那么您将使用更新的GZipStream。这是因为它位于System.dll中,这是一个受支持的库。您可以使用允许CompressionLevel的新构造函数来测试这一点。只需将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实际上做得稍微好一些。
  3. CompressionMode.CompressCompressionLevel.Optimal在功能上等价。在指定对方时,每一个都是假定的默认值。
  4. 不要对输入参数使用string;使用SqlString
  5. 去掉byte[] bytes
  6. 将第一个new MemoryStream( bytes )块中的using更改为: new MemoryStream(str.GetUnicodeBytes())
  7. 您可以去掉if( str == null ){return new SqlBinary();}行。不要在.NET代码中处理这个问题,只需将WITH RETURNS NULL ON NULL INPUT添加到创建功能中即可。这样,如果输入为NULL :),Server甚至不会调用您的代码。请记住,当您有多个输入参数时,如果其中任何一个参数为NULL,则此选项将返回NULL。如果它们中至少有一个能够传递NULL,那么您就必须在代码中处理这种情况。
  8. 将这一行if( String.IsNullOrEmpty( str ) ){str = " ";}替换为: if (str.Value.Length == 0) {返回SqlBinary.Null;}
  9. 我还没有尝试过"zlib“,但不幸的是,"SharpZipLib”和"DotNotZip“都是错误的,而且几年没有更新,也没有迹象表明它们将被更新。然而,"DotNetZip“中的bug似乎主要是关于压缩文件归档的,而不是GZip功能(在SQL#:-中工作得很好)。
票数 5
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/89362

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档