【问题标题】:Most Space-Efficient Way to Store a Byte Array in a Database Table - ASP.NET在数据库表中存储字节数组的最节省空间的方法 - ASP.NET
【发布时间】:2012-11-02 20:25:57
【问题描述】:

现在我们有一个数据库表 (SQL Server 2008 R2),它在图像类型列中存储上传的文件(PDF、DOC、TXT 等)。用户从 ASP.NET 应用程序上传此文件。我的项目是处理这个表的增长大小,并且在此过程中我提出了几个问题。

  1. 在数据库方面,我发现图像列类型据说有些贬值?我是否会从切换到 varbinary(max) 获得任何好处,或者我应该说 varbinary(5767168),因为这是我的文件大小上限,或者我也可以让它保持为图像类型,只要空间效率是担心吗?

  2. 在应用程序端,我想压缩字节数组。微软内置的 GZip 有时会使文件变大而不是变小。我切换到 SharpZipLib,它好多了,但我仍然偶尔会遇到同样的问题。在我大规模实施之前,有没有办法找出平均文件压缩节省?我很难找出他们使用的底层算法。

  3. 是否值得我自己编写一个霍夫曼代码算法,或者在压缩文件偶尔比原始文件大的情况下也会出现同样的问题?

作为参考,以防万一,这是我的应用程序中的代码:

    using ICSharpCode.SharpZipLib.GZip;

    private static byte[] Compress(byte[] data)
    {
        MemoryStream output = new MemoryStream();

        using (GZipOutputStream gzip = new GZipOutputStream(output))
        {
            gzip.IsStreamOwner = false;
            gzip.Write(data, 0, data.Length);
            gzip.Close();
        }
        return output.ToArray();
    }

    private static byte[] Decompress(byte[] data)
    {
        MemoryStream output = new MemoryStream();
        MemoryStream input = new MemoryStream();
        input.Write(data, 0, data.Length);
        input.Position = 0;

        using (GZipInputStream gzip = new GZipInputStream(input))
        {
            byte[] buff = new byte[64];
            int read = gzip.Read(buff, 0, buff.Length);

            while (read > 0)
            {
                output.Write(buff, 0, read);
                read = gzip.Read(buff, 0, buff.Length);
            }

            gzip.Close();
        }
        return output.ToArray();
    }

提前感谢您的帮助。 :)

【问题讨论】:

  • 对 SQL Server/这类问题的处理还不够,但我听说资源通常不会持久化到数据库本身(特别是对于大文件之类的东西),只有参考到网络服务器上的位置。
  • 您可能需要考虑为压缩算法设置一个单独的列。这样,您可以随着时间的推移针对不同的文件类型使用不同的算法,或者请注意,如果压缩只会导致数据增长,则不使用压缩。
  • Clockwork-Muse,如果将来某个时间点移动文件,则存在链接错误的风险。除了一位碰巧知道不应移动这些特定文件的程序员之外,您没有任何东西可以连接链接和文件。有些东西可能没问题,但在我的情况下,这些是敏感的法律文件,所以无论好坏,我们都希望确保它们留在那里。鉴于此约束,压缩是一种稍微减轻尺寸爆炸的方法。无论如何感谢您的建议!

标签: asp.net sql sql-server-2008 compression sharpziplib


【解决方案1】:

那不是字节数组,那是 BLOB。 10 年前,您会使用 IMAGE 数据类型。

如今,使用 VARBINARY(MAX) 效率更高 我真的建议人们将 FILESTREAM 用于 VarBinary(Max),因为它使备份数据库(没有 blob)变得非常容易。

请记住,使用本机格式(无压缩)将允许全文搜索。如果您考虑一下,这真是令人难以置信。您必须从 Adob​​e 安装一些 iFilter 才能在 PDF 中进行搜索。但这是一个杀手级功能,我不能没有它。

【讨论】:

  • 对!这是我的应用程序中的字节数组。 :) 您是否有任何资料表明 varbinary(max) 类型比 Image 类型更有效?您的意思是 varbinary 类型更节省空间、更节省时间,还是两者兼而有之?尽管我不需要该功能,但在其中进行搜索是一个非常不错的功能,而且我怀疑它一旦被压缩就可以处理数据。
  • 文件流数据不是像普通数据一样备份吗?它必须保持一致性。
  • 文件流对象可以包含或排除在备份中。我知道这听起来没什么大不了的。但我与太多的 blob 合作过,总是想支持它们。
  • 也.. 我 - 认为 - 你 - 可能 - 能够为此使用 NTFS 压缩,并且仍然支持 FullTextSearch。我知道在假设它不是一个选项之前我至少会尝试一下。
  • 看来我错了。我记得在 SQL 2008 中,我渴望让压缩工作......我认为他们将在未来的版本中提供它。我还没有检查是否在 SQL 2012 中可用。
【解决方案2】:

我不想成为一个混蛋并回答我自己的问题,但我想我会将我的发现总结为一个完整的答案,以供其他希望在数据库中高效存储文件/图像数据的人使用:

* 使用 varbinary(MAX) 与 Image?

使用 varbinary(MAX) 的原因有很多,但其中最重要的是 Image 已被弃用,并且在未来的 SQL 版本中将完全删除它。不使用它开始任何新项目只是将未来的问题扼杀在萌芽状态。

根据这个问题中的信息:SQL Server table structure for storing a large number of images,varbinary(MAX) 有更多可用的操作。

Varbinary(MAX) 很容易通过使用 SQL 参数从 .NET 应用程序流式传输。负数是“MAX”长度。像这样:

SQLCommand1.Parameters.Add("@binaryValue", SqlDbType.VarBinary, -1).Value = compressedBytes;

* 使用什么压缩算法?

在这个问题上,我真的离一个体面的答案不远了。我使用 ICSharpCode.SharpZipLib.Gzip 并发现它比内置的压缩​​功能具有更好的性能,只需在一堆东西上运行它并进行比较。

我的结果:

我将总文件大小减少了大约 20%。不幸的是,我拥有的很多文件都是压缩得不好的 PDF,但仍然有一些好处。已经压缩的文件类型(显然)运气不佳。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-08
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多