【问题标题】:Should I use MySQL blob field type?我应该使用 MySQL blob 字段类型吗?
【发布时间】:2010-12-15 14:14:14
【问题描述】:

我正在努力决定是否应该在即将进行的项目中使用 MySQL blob 字段类型。

我的基本要求是,可以查看某些数据库记录,并上传多个文件并“附加”到这些记录。根据具体情况,查看所述记录可能仅限于某些人。几乎没有任何限制可以上传任何类型的文件。

所以从一个角度来看,如果我走 MySQL 路线,我不必担心病毒蔓延或随机 php 文件被上传并以某种方式执行。我还有一个更简单的方法来获得许可并将数据与记录相关联。

另一个明显的方法是将数据存储在 webroot 之外的特定文件夹结构中。在这种情况下,我必须为文件夹/文件制定一个特殊的命名约定,以跟踪它们在数据库中引用的内容。

使用 MySQL blob 字段类型是否会影响性能?我担心选择会阻碍网站未来发展的解决方案以及选择不容易维护的解决方案。

【问题讨论】:

    标签: mysql


    【解决方案1】:

    使用 MySQL blob 字段类型是否会影响性能?

    不是天生的,但是如果有大 BLOB 堵塞了表和内存缓存,那肯定会导致性能下降。

    另一个明显的方法是将数据存储在 webroot 之外的特定文件夹结构中。在这种情况下,我必须为文件夹/文件制定一个特殊的命名约定,以跟踪它们在数据库中引用的内容。

    是的,这是一种常见的方法。你通常会做一些事情,比如让文件夹以它们关联的每个表命名,包含仅基于主键的文件名(理想情况下是一个整数;当然绝不是用户提交的任何内容)。

    这是一个更好的主意吗?这取决于。仅拥有一个数据存储具有部署简单的优势,并且不必担心授予 Web 用户对任何内容的写入权限。此外,如果可能有多个应用程序副本正在运行(例如主动-主动负载平衡),那么您需要同步存储,这对于数据库来说要比使用文件系统容易得多。

    如果您确实使用文件系统而不是 blob,那么问题是,您是否通过将别名指向文件夹来让 Web 服务器为其提供服务?

    • + 超级快
    • + 缓存良好
    • - 额外的服务器配置:虚拟目录;需要适当的文件扩展名才能返回所需的Content-Type
    • - 额外的服务器配置:作为反 XSS 措施的一部分,需要添加 Content-Disposition: attachment/X-Content-Type-Options 标头来停止 IE 对 HTML 的嗅探

    还是像您必须从 MySQL blob 提供服务一样,通过让服务器端脚本将其输出来手动提供文件?

    • - 可能很慢
    • - 需要相当多的手动 If-Modified-Since 和 ETag 处理才能正确缓存
    • + 可以使用应用程序自己的访问控制方法
    • + 从服务脚本中轻松添加正确的 Content-Type 和 Content-Disposition 标头

    这是一种权衡,没有一个全球公认的答案。

    【讨论】:

      【解决方案2】:

      如果您的网络服务器将通过网络提供这些上传的文件,那么如果将它们存储在文件系统上,性能几乎肯定会更好。然后,Web 服务器将能够应用 HTTP 缓存提示,例如 Last-ModifiedETag,这将有助于提高用户多次访问同一文件的性能。此外,Web 服务器会在服务时自动为文件设置正确的Content-Type。如果您将 blob 存储在数据库中,您最终将实现上述功能以及更多功能,而您应该从您的 Web 服务器免费获取它们。

      此外,从数据库中提取大型 blob 数据可能最终成为数据库的性能瓶颈。此外,您的数据库备份可能会更慢,因为它们将备份更多数据。如果您在开发期间进行临时查询,那么在select 语句的结果集中看到大块会很不方便。如果你想简单地检查一个上传的文件,这样做会很不方便和迂回,因为它会笨拙地存储在数据库列中。

      我会坚持将文件存储在文件系统上的常见做法以及数据库中文件的路径。

      【讨论】:

        【解决方案3】:

        根据我的经验,在 MySQL 中存储 BLOB 是可以的,只要您只将 blob 存储在一个表中,而其他字段存储在另一个(连接的)表中。相反,在包含几个标准字段和一个包含 100 MB 数据的 blob 字段的表的字段中进行搜索会显着降低查询速度。

        我不得不针对这个问题更改邮件应用程序的数据层,其中电子邮件的内容与发送日期、电子邮件地址等存储在同一个表中。搜索 10000 封电子邮件需要 9 秒。现在它需要它应该需要的东西;-)

        【讨论】:

          【解决方案4】:

          许多人建议不要将文件附件(通常这适用于图像)存储在数据库中的 blob 中。相反,他们更喜欢将路径名作为字符串存储在数据库中,并将文件存储在文件系统上的某个安全位置。这样做有一些优点:

          • 数据库和数据库备份更小。
          • 如果您需要临时处理文件系统上的文件,则更容易编辑它们。
          • 文件系统擅长存储文件。数据库擅长存储元组。让每个人都做自己擅长的事。

          也有反对意见,支持将附件放在一个 blob 中:

          • 删除数据库中的一行会自动删除关联的附件。
          • 当数据在一行中时,回滚和事务隔离按预期工作,但当部分数据在文件系统上时,则不会。
          • 如果所有数据都在数据库中,备份会更简单。无需担心对备份过程中同时更改的数据进行一致的备份。

          因此,最佳解决方案取决于您将如何在应用程序中使用数据。没有万能的答案。

          我知道您使用 MySQL 标记了您的问题,但如果阅读此问题的人使用其他品牌的 RDBMS,他们可能希望在使用 Oracle 时查看BFILE,或者在使用 Microsoft SQL Server 2008 时查看FILESTREAM。这些给出您可以将文件存储在数据库之外,但可以像访问数据库表中的一行一样访问它们(或多或少)。

          【讨论】:

            【解决方案5】:

            数据应该存储在一个一致的地方:数据库。 这种性能和 Content-Type 根本不是问题,因为没有什么可以阻止您将这些 BLOB 字段缓存到本地 Web 服务器并在第一次请求时从那里提供服务。您无需在每次页面浏览时都访问该表。

            此文件系统缓存可以随时清空,这只会暂时影响性能,因为它会自动重新填充。随着应用程序的增长,它还使您能够使用一个数据库和多个 Web 服务器,它们都将在文件系统上拥有一个本地缓存。

            【讨论】:

              【解决方案6】:

              大量数据最终会对性能造成影响。 MS SQL 2008 有一种在文件系统中存储二进制数据的特殊方式:

              http://msdn.microsoft.com/en-us/library/cc949109.aspx

              我也会为您的项目采用类似的方法。

              您可以创建一个 FILES 表来保存有关文件的信息,例如原始名称。为了在磁盘上安全地存储文件,例如使用 GUID 重命名它们。将新文件名存储在您的 FILES 表中,当用户需要下载它时,您可以轻松地在磁盘上找到它并将其流式传输给用户。

              【讨论】:

                【解决方案7】:

                在我看来,将文件存储在数据库中是个坏主意。您可以在那里存储的内容是 id、名称、类型、可能是文件的 md5 哈希值和插入的日期。文件可以上传到公共位置以外的文件夹。此外,您应该注意的是,不建议在一个文件夹中保存超过 1000 个文件。因此,每次文件 id 增加 1000 时,您必须创建新文件夹。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2020-01-23
                  • 1970-01-01
                  • 2011-01-12
                  • 1970-01-01
                  • 2012-02-20
                  • 2010-10-18
                  • 2012-03-04
                  • 1970-01-01
                  相关资源
                  最近更新 更多