我应该使用MySQL blob字段类型吗?

时间:2009-11-11 18:44:08

标签: mysql

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

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

所以从一个方面来看,如果我走MySQL路线,我不必担心病毒的爬行或随机的php文件上传并以某种方式执行。我还有一个更容易获得许可的途径,并保持数据与记录接近。

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

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

7 个答案:

答案 0 :(得分:11)

  

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

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

  

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

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

这是一个更好的主意吗?这取决于。只有一个数据存储有简单的部署优势,而且不必担心让Web用户对任何东西进行写访问。此外,如果可能有多个应用程序副本正在运行(例如,主动 - 主动负载平衡),那么您需要同步存储,这对于数据库而言比使用文件系统更容易。

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

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

或者您是否通过将服务器端脚本吐出来手动提供文件,因为您必须从MySQL blob提供服务?

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

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

答案 1 :(得分:10)

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

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

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

答案 2 :(得分:5)

根据我的经验,在MySQL中存储BLOB是可以的,只要您将blob存储在一个表中,而其他字段存储在另一个(连接)表中。相反,在具有几个标准字段的表的字段和具有100 MB数据的一个blob字段中搜索可以显着减慢查询。

我不得不为此问题更改邮件应用的数据层,其中电子邮件与发送日期,电子邮件地址等相同的表中的内容一起存储。搜索10000封电子邮件需要9秒。现在需要采取的措施; - )

答案 3 :(得分:3)

数据应存储在一个统一的位置:数据库。 这种性能和内容类型的东西根本不是问题,因为没有什么能阻止您将这些BLOB字段缓存到本地Web服务器并在第一次请求时从那里提供服务。您无需在每个页面视图上访问该表。

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

答案 4 :(得分:2)

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

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

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

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

答案 5 :(得分:2)

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

  • 数据库和数据库备份较小。
  • 如果您需要临时使用它们,则可以更轻松地编辑文件系统上的文件。
  • 文件系统擅长存储文件。数据库擅长存储元组。让每个人都做自己擅长的事。

也存在反驳,支持将附件放入blob:

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

因此,最佳解决方案取决于您将如何在应用程序中使用数据。没有一个适合所有人的答案。

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

答案 6 :(得分:0)

在我看来,在数据库中存储文件是个坏主意。您可以存储的内容有id,名称,类型,可能是文件的md5哈希值和插入的日期。文件可以上传到公共场所外的文件夹。另外,您应该担心不建议在一个文件夹中保留1000个以上的文件。因此,每当文件ID增加1000时,您必须创建新文件夹。