在数据库中存储图像 - 是还是不是?

415

我正在使用一款将图片大量存储在数据库中的应用程序。你对此有何看法?我更倾向于将其位置存储在文件系统中,而不是直接存储在数据库中。

你认为这样做的利弊是什么?


好的,你可以使用事务性磁盘缓存来实现这两个功能。 - Lilith River
56个回答

350

我负责管理一些处理数千GB图像的应用程序,我们发现在数据库中存储文件路径是最佳选择。

但有几个问题:

  • 相比于文件系统存储,数据库存储通常更昂贵
  • 您可以通过标准的现成产品来提高文件系统访问速度
    • 例如,许多Web服务器使用操作系统的sendfile()系统调用将文件直接从文件系统异步发送到网络接口。存储在数据库中的图像无法受益于此优化。
  • 像Web服务器等需要访问文件系统中的图像时无需特殊编码或处理
  • 在涉及图像和元数据之间的事务完整性方面,数据库胜出。
    • 管理数据库元数据与文件系统数据之间的完整性更加复杂
    • 难以保证数据已在文件系统上刷新(在Web应用程序的上下文中)

33
有哪些现成的产品可以用来“超级加速”文件系统? - Andrei Rînea
22
虽然我的文件只有3TB,但我完全同意。数据库适用于结构化数据,而不是二进制大对象(BLOB)。 - derobert
7
如果您永远不会在查询中使用某个数据元素,作为条件或用于连接,则该元素可能不属于数据库。但如果您有一个很好的数据库函数来查询相似的图像... - Nils Weinander
14
有哪些现成产品可用于"超级加速"文件系统? - faceclean
5
回复:"超加速"产品:现在,大多数Web服务器都可以利用sendfile()系统调用,将静态文件异步地传递给客户端。 它将从磁盘到网络接口的文件移动任务卸载给操作系统。 操作系统可以更有效地执行此操作,运行在内核空间中。对我来说,这似乎是文件系统与数据库相比存储/提供图像的重要胜利。 - Alan Donnelly
显示剩余9条评论

140
和大多数问题一样,情况并不像听起来那么简单。有些情况下,在数据库中存储图像是有意义的。
  • 您正在存储动态更改的图像,例如发票,并且您想获取1 Jan 2007上的发票?
  • 政府要求您保留6年历史记录
  • 存储在数据库中的图像不需要不同的备份策略。存储在文件系统上的图像需要
  • 如果图像位于数据库中,则更容易控制对其的访问。空闲管理员可以访问磁盘上的任何文件夹。需要一个非常决心的管理员才能查看数据库以提取图像
另一方面,也存在问题:
  • 需要额外的代码来提取和流式传输图像
  • 延迟可能比直接访问文件慢
  • 会给数据库服务器带来更重的负载

2
如果您编写的应用程序是安装在本地(例如 SharePoint)上的,则没有单独的备份策略可能会成为一个大问题。当您创建 SharePoint 备份时,所有内容都在数据库中,这使得备份非常容易。 - Eric Schoonover
44
通过模糊性来保证安全并不是真正的访问控制策略! - Jon Cage
5
我认为他并不主张通过保密来确保安全性 - 他说将图像存入数据库可以增加一层安全保障。(我想……@Conrad,不想替你发言) - AJ.
我选择将图像存储在数据库中,因为它具有单一备份优势(或更普遍地说,所有数据都在一个地方),但你提到的问题也是真实存在的,这就是为什么我会在文件系统上缓存图像。这是两全其美的最佳选择,我很惊讶这里的顶级答案中没有提到它。 - Bart van Heukelom
你是否碰巧正在使用 the ImageResizing.Net 库来处理将 SQL 缓存到磁盘上的图像?它是目前最先进、可扩展和强大的磁盘缓存。 - Lilith River
@Conrad:那小尺寸的图片呢?我相信在这两种情况下,图片的检索性能也取决于图片的大小对吧?比如说,如果是用户的个人资料照片,是否建议将其存储在数据库中? - Rajat Gupta

99

ext3的dir_index非常有帮助。 - Seun Osewa

56

这可能有点冒险,但如果您正在使用(或计划使用)SQL Server 2008,我建议看一下新的FileStream数据类型。

FileStream解决了大部分在DB中存储文件的问题:

  1. Blobs实际上存储为文件夹中的文件。
  2. Blobs可以使用数据库连接或文件系统访问。
  3. 备份得到了集成。
  4. 迁移“只需运行”。

然而,SQL的“透明数据加密”不会加密FileStream对象,因此如果考虑到这一点,最好将它们存储为varbinary。

从MSDN文章中可以了解到:

  

Transact-SQL语句可以插入、更新、查询、搜索和备份FILESTREAM数据。Win32文件系统接口提供对数据的流式访问。
  FILESTREAM使用NT系统缓存来缓存文件数据。这有助于减少FILESTREAM数据对数据库引擎性能的影响。不使用SQL Server缓冲池; 因此,该内存可用于查询处理。


+1 对于 FileStream。它实际上将 blob 存储为磁盘上的文件,但以事务方式管理它们。 - John Gietzen
此外,SQL Server 允许直接从磁盘访问 FileStream blobs,这样您就可以避免占用数据库连接。 - John Gietzen
仍然存在数据库和Web服务器之间的延迟...而且Web服务器必须将其加载到内存中以流式传输到客户端,而无法直接从磁盘流式传输,除非你使用了磁盘缓存。 - Lilith River

39

在数据库中使用文件路径绝对是正确的选择 - 我听过很多客户的故事,他们有TB级别的图片需要存储,将这些图片存储在数据库中成为了一场噩梦 - 单单是性能损失就已经太大了。


35

根据我的经验,有时候最简单的解决方案就是按照主键命名图片。这样很容易找到属于特定记录的图片,反之亦然。但同时,您并未在数据库中存储任何与图片相关的信息


非常好。现在您的用户可以轻松地递增文件名以访问其他文件... - Marijn Huizendveld
6
只有当你将图片暴露给公众时,才会发生这种情况。 - Seun Osewa
我们在图像文档方面做了类似的事情(我们的主键是由三个项目组成的复合键),但我们添加了文档扫描的日期和时间,以便我们可以在同一个目录中拥有多个版本。 - Andrew Neely
@Osewa,这样怎么样?是的,要直接访问文件,最终用户需要访问该文件夹。您可以通过请求基于FTP提供文件的过程,并且安全性与SQL服务器相当。 - Andrew Neely

31

关键在于不要成为一个狂热者。

值得注意的一点是,文件系统阵营中没有人列出特定的文件系统。这是否意味着从FAT16到ZFS的所有内容都轻松打败了每个数据库?

不是的。

事实上,许多数据库甚至在仅谈论原始速度时也能击败许多文件系统。

正确的做法是为您的精确场景做出正确的决策,并为此,您需要一些数字和一些用例估计。


6
我没有看到任何人声称文件系统在所有情况下都比数据库快(请参考Mark Harrison的回答)。这有点像草人论法。可能有一些情况不戴安全带更好,但总的来说,系安全带是一个好主意。 - Calvin

30

在必须保证引用完整性和ACID兼容性的地方,将图像存储在数据库中是必需的。

您无法事务性地保证存储在数据库中的图像及其元数据引用同一文件。换句话说,无法保证在文件系统上的文件只会在同一时间和同一事务中与元数据一起更改。


7
实际上,是可以的。只要在创建图像文件后从未删除、更改或覆盖图像文件,所有图像文件在尝试提交事务之前都已同步,并且没有文件系统损坏,您就可以确保图像文件和元数据是同步的。对于某些应用程序来说,这些条件可能太多了吧。 - Seun Osewa
我甚至可以进一步说,通过使用日志文件系统和一些额外的程序逻辑,可以实现ACID兼容性。具体步骤是先写入数据库记录,再写入文件。如果文件提交成功,则提交数据库事务。 - Andrew Neely

28

正如其他人所说,SQL 2008带有一种名为Filestream的类型,允许您将文件名或标识符存储为指针在数据库中,并自动将图像存储在文件系统中,这是一个很好的场景。

如果您使用较旧的数据库,则我会建议,如果您将其存储为blob数据,则无法从数据库中获得任何搜索功能,因此最好将地址存储在文件系统上,并以这种方式存储图像。

这样,您还可以节省文件系统上的空间,因为您只需要保存确切的空间量,甚至是压缩后的空间量。

此外,您可以决定使用某些结构或元素保存原始图像,允许您在没有任何数据库访问的情况下浏览文件系统中的原始图像,或者批量传输文件到另一个系统、硬盘驱动器、S3或其他情况——在程序中更新位置,但保持结构,而不需要试图从数据库中提取图像时受到过多影响以增加存储。

可能,这也允许您向基于常见图像url的缓存元素抛一些东西,以便在您的Web引擎/程序中节省自己。


27

小型静态图片(不超过几兆)且不经常编辑的可存储在数据库中。该方法有多个优点,包括更便于移植(图像随数据库一起传输)、更便于备份/恢复(图像与数据库一起备份)和更好的可扩展性(一个文件系统文件夹有成千上万的缩略图文件听起来像是一个可扩展性的噩梦)。

从数据库提供图像很容易,只需实现一个HTTP处理程序,将从DB服务器返回的字节数组作为二进制流提供即可。


我认为对于经常编辑的文件,数据库更好,因为在这种情况下一致性可能是一个问题。 - Seun Osewa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接