在DB中存储图像-是或否?


415

因此,我正在使用一个将图像大量存储在数据库中的应用程序。您对此有何看法?我更喜欢将位置存储在文件系统中,而不是直接将其存储在数据库中。

您认为优点/缺点是什么?


好吧,您可以同时使用事务性磁盘缓存
莉莉丝·利弗

Answers:


350

我负责管理许多TB图像的一些应用程序。我们发现最好将文件路径存储在数据库中。

有几个问题:

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

33
有哪些现成的产品可用于“超级加速”文件系统?
AndreiRînea'08年

22
虽然我只管理3TB的文件,但我绝对同意。数据库用于结构化数据,而不是blob。
derobert

7
@derobert:的确如此,如果您永远不会在查询中使用数据元素作为条件或进行联接,则该数据元素可能不属于数据库。再说一次,如果您有一个很好的数据库功能来查询图像是否相似...
Nils Weinander 09年

14
有哪些现成的产品可用于“超级加速”文件系统?
ablmf

5
回复:“超级加速”产品:现在大多数Web服务器都可以利用sendfile()系统调用将静态文件异步传递到客户端。它将将文件从磁盘移动到网络接口的任务卸载到操作系统。操作系统可以在内核空间中更有效地执行此操作。对我来说,这似乎是文件系统与db存储/服务映像的大赢家。
艾伦·唐纳利

140

与大多数问题一样,它并不像听起来那样简单。在某些情况下,将图像存储在数据库中是有意义的。

  • 您要存储动态变化的图像(例如发票),并且想要获得2007年1月1日的发票吗?
  • 政府希望您保持6年的历史
  • 存储在数据库中的映像不需要其他备份策略。存储在文件系统上的图像可以
  • 如果图像在数据库中,则更容易控制对图像的访问。空闲管理员可以访问磁盘上的任何文件夹。真正确定的管理员需要窥探数据库来提取图像

另一方面,存在相关的问题

  • 需要其他代码来提取和流式传输图像
  • 延迟可能比直接文件访问慢
  • 数据库服务器上的负载较重

2
在编写在内部安装的应用程序(如SharePoint)时,没有单独的备份策略可能会很重要。创建SharePoint备份时,所有内容都在数据库中,这非常容易。
Eric Sc​​hoonover,

44
默默无闻的安全性并不是真正的访问控制策略!
乔恩·凯奇

5
我不认为他过分提倡安全性-他是说将图像放入数据库会增加另一层安全性。(我认为... @Conrad,不想在嘴里说些什么)
AJ。

我之所以选择将图像存储在数据库中是因为具有单一备份的优势(或更笼统地说,将所有数据都放在一个位置),但是您提到的问题也是如此,这就是为什么我将图像缓存在文件系统上。这是两全其美的方法,令我惊讶的是,这里没有一个最佳答案。
Bart van Heukelom

您是不是偶然使用ImageResizing.Net库来处理SQL->磁盘图像缓存?它是您可以获得的最先进,可扩展性最强的磁盘高速缓存...
Lilith River


56

这可能会花费很多时间,但是如果您正在使用(或计划使用)SQL Server 2008,我建议您看看新的FileStream数据类型。

FileStream解决了将文件存储在DB中的大多数问题:

  1. Blob实际上是作为文件存储在文件夹中的。
  2. 该斑点可使用被访问或者数据库连接在文件系统中。
  3. 备份已集成。
  4. 迁移“行之有效”。

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

从MSDN文章:

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


为FileStream +1。它实际上将Blob作为文件存储在磁盘上,但通过事务进行管理。
John Gietzen

此外,SQL Server允许直接从磁盘访问FileStream Blob,这样您就可以避免束缚数据库连接
John Gietzen

尽管如此,数据库和Web服务器之间的等待时间仍然增加了……除非您使用磁盘缓存,否则Web服务器将必须将其加载到内存中以将其流式传输到客户端,而不是能够从磁盘流式传输。
莉莉丝·利弗

39

数据库中的文件路径绝对是必经之路-我听到一个接一个的故事,有TB图像的客户说,试图在DB中存储任何数量的图像成为一场噩梦-仅性能方面的影响就太大了。


35

以我的经验,有时最简单的解决方案是根据主键命名图像。因此,很容易找到属于特定记录的图像,反之亦然。但是同时,您不会在数据库中存储有关图像的任何内容。


的确很好。您的用户现在可以轻松地增加文件名来访问其他文件...
Marijn Huizendveld 2010年

6
@Marijn:只有在您将图像公开的情况下。
Seun Osewa 2010年

我们对图像文档进行了非常相似的操作(我们的主键是三项的组合键。),但是我们添加了扫描文档的日期和时间,以便我们可以在同一目录中拥有多个版本。
Andrew Neely

@Osewa,那怎么样?是的,要直接访问文件,最终用户将需要访问该文件夹。您可以有一个根据请求通过FTP为文件提供文件的过程,其安全性与SQL Server相当。
Andrew Neely

31

这里的诀窍是不要成为狂热分子。

这里要注意的一件事是,亲文件系统阵营中没有人列出特定的文件系统。这是否意味着从FAT16到ZFS的所有内容都能轻松击败每个数据库?

没有。

事实是,即使我们只是在谈论原始速度,许多数据库还是击败了许多文件系统。

正确的做法是为您的精确方案做出正确的决定,并且要这样做,您将需要一些数字和一些用例估计。


6
我看不到有人声称文件系统比数据库快100%的时间(请阅读Mark Harrison的答案)。那有点像个稻草人。在某些情况下,最好不系安全带,但总的来说,系好安全带是个好主意。
加尔文

30

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

您不能交易保证图像和存储在数据库中的图像相关的元数据引用相同的文件。换句话说,不可能保证文件系统上的文件仅与元数据同时在同一事务中进行更改。


7
实际上,不可以。只要映像文件在创建后再也不会被删除,更改或覆盖,则在尝试提交事务之前所有映像文件都已同步,没有文件系统损坏,您可以确保映像文件和元数据是同步的。我猜对于某些应用程序来说,这些ifs太多了。
Seen Osewa

我还要说的是,有了日记文件系统和一些其他程序逻辑,就可以实现ACID合规性。步骤将是写db记录,写文件。如果文件提交,请提交数据库事务。
Andrew Neely

28

正如其他人所说,SQL 2008带有Filestream类型,该类型允许您将文件名或标识符作为指针存储在db中,并自动将映像存储在文件系统中,这是一个很好的方案。

如果您使用的是较旧的数据库,那么我想说的是,如果将其存储为Blob数据,那么您实际上不会从搜索功能中从数据库中获取任何东西,因此,最好是在文件系统上存储地址,并以这种方式存储映像。

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

另外,您可以决定保存一些结构或元素,以使您能够浏览文件系统中的原始图像而没有任何数据库命中,或将文件批量传输到另一个系统,硬盘驱动器,S3或另一个方案中-更新其中的位置您的程序,但保持结构,再次尝试增加存储量时,尝试将图像从数据库中取出来并没有太大的影响。

可能还会允许您根据常用的图像URL向Web引擎/程序中添加一些缓存元素,因此您也可以将自己保存在那里。


27

不经常编辑的小型静态图像(不超过几个兆)应存储在数据库中。此方法具有以下优点:易于移植(通过数据库传输图像),更容易备份/还原(通过数据库备份图像)和更好的可伸缩性(带有数千个小缩略图文件的文件系统文件夹听起来像是可伸缩性的噩梦)我)。

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


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

26

这是有关该主题的有趣的白皮书。

到BLOB或不到BLOB:数据库或文件系统中的大对象存储

答案是“视情况而定”。当然,这将取决于数据库服务器及其Blob存储方法。它还取决于存储在Blob中的数据类型,以及如何访问该数据。

使用数据库作为存储机制,可以有效地存储和传送较小尺寸的文件。较大的文件可能最好使用文件系统来存储,尤其是如果它们经常被修改/更新时。(斑点分散成为性能问题。)

还有一点要牢记。支持使用数据库存储Blob的原因之一是ACID合规性。但是,测试人员在白皮书中使用的方法(SQL Server的“大容量日志记录”选项)使SQL Server的吞吐量增加了一倍,有效地将ACID中的“ D”更改为“ d”,因为未使用Blob数据记录事务的初始写入。因此,如果完全ACID合规性是您系统的重要要求,则在将文件I / O与数据库Blob I / O进行比较时,将数据库写入的SQL Server吞吐量数据减半。


25

我尚未见任何人提及的一件事,但绝对值得注意的是,在大多数文件系统中存储大量图像也存在一些问题。例如,如果您采用上述方法,并以主键命名每个图像文件,那么在大多数文件系统上,如果您将所有图像都放置在一个很大的目录中,一旦尝试将所有图像放置在一个大目录中,就会遇到问题(例如数十万或数百万)。

一种常见的解决方案是将它们散列到平衡的子目录树中。


您可能会这么认为,但实际上问题很小。我有一个应用程序,它在一个目录中包含数百万个文件,可以被数百个用户访问,没有问题。这不是很聪明,但是可以。最大的问题是,如果使用资源管理器浏览目录,则会永远观看手电筒。
SqlACID

1
最好使用对大目录没有问题的文件系统
Seun Osewa

8
我有一个应用程序,该应用程序在一个目录(运行RHEL 4的服务器)中包含数百万个文件-甚至列出目录内容(将文件插入到文件中)都花了几天时间,并创建了100 MB大小的输出文件。现在它们在数据库中,我只有一个文件,可以很容易地移动或备份它。
理查德

1
@Seun Osewa:每个文件系统都有局限性...如果您知道在同一个目录中存储数百万个条目没有问题,请告诉我!
纪尧姆

1
@Seun Osewa:数据库现在高达28GB,具有540万条记录。我最终不得不对数据库表进行分区,所以我要备份几个大约5GB的文件,现在将单个图像移动到Amazon S3上,因此我只需要将文件名存储在数据库中(Amazon可以进行备份) )
理查德(Richard

22

没有人提到过,数据库保证原子动作,事务完整性和并发性。即使是文件系统,参照完整性也无法显示-那么您如何知道您的文件名确实仍然正确?

如果您将图像保存在文件系统中,并且在编写新版本甚至删除文件时有人正在读取文件-会发生什么?

我们使用Blob是因为它们也更易于管理(备份,复制,传输)。他们为我们运作良好。


对特定图像进行两次同时更新的可能性是多少?
Arafangion

1
您不需要同时进行更新就可以解决问题-它可以是读写操作。在我们的情况下,几乎可以肯定会发生这种情况。
Draemon

20

仅将图像的文件路径存储在数据库中的问题是不再可以强制数据库的完整性。

如果文件路径指向的实际映像不可用,则数据库会不经意间出现完整性错误。

假设图片是所追求的实际数据,并且可以在一个集成数据库中更轻松地进行管理(图片不会突然消失),而不必与某种文件系统进行交互(如果文件系统是独立访问的,图像可能突然“消失”),我将其直接存储为BLOB等。


17

在我曾经工作过的一家公司中,我们在Oracle 8i(当时为9i)数据库中存储了1.55亿张图像。价值7.5TB。


5
绝对。显然,数据库现在更大了。将数据存储在数据库中意味着在不同站点上复制数据库也容易得多。
graham.reeds

我看到了一个Oracle演示,该演示实际上可以将文件系统挂载到数据库或类似的东西。你知道这是你干的吗?(对不起,我对Oracle一无所知,所以也许我在谈论垃圾。)
Stu Thompson,2009年

我不这么认为-它是将图像作为数据库存储在数据库中。数据库进行了积极的调整-我记得在添加和删除字段时有关图像大小更改的多次讨论。一切都是边界对齐的。
graham.reeds

14

通常,我坚决反对采用最昂贵,最难扩展的基础架构(数据库)部分并将所有负载放入其中。另一方面:它极大地简化了备份策略,尤其是当您有多个Web服务器并且需要以某种方式保持数据同步时。

像大多数其他事情一样,这取决于预期的规模和预算。


13

我们已经实现了一个文档映像系统,它将所有图像存储在SQL2005 blob字段中。目前有数百GB,我们看到响应时间极好,性能几乎没有下降。此外,为了符合法规要求,我们还有一个中间件层,可将新发布的文档存档到光学自动点唱机系统,该系统将其公开为标准NTFS文件系统。

我们对结果感到非常满意,尤其是在以下方面:

  1. 易于复制和备份
  2. 能够轻松实现文档版本控制系统

11

如果这是基于Web的应用程序,则将图像存储在第三方存储交付网络(例如Amazon的S3或Nirvanix平台)上可能会有优势。


11

假设:应用程序已启用网络/基于网络

令我惊讶的是,没有人真正提到这一点...将其委托给其他专家-> 使用3rd第三方图像/文件托管服务提供商

将文件存储在付费在线服务上,例如

另一个StackOverflow线程在这里谈论这个问题

该线程说明了为什么您应该使用第三方托管服务提供商。

非常值得。他们有效地存储它。没有带宽从您的服务器上传到客户端请求等。


10

如果您不在SQL Server 2008上,并且有一些充分的理由将特定的图像文件放入数据库中,则可以采用“两种”方法,并将文件系统用作临时缓存,并将数据库用作主存储库。

例如,您的业务逻辑可以在提供图像文件之前检查磁盘上是否存在图像文件,并在必要时从数据库中检索。这为您提供了多个Web服务器的功能,并减少了同步问题。


+1这还允许您存储原始图像,提供缓存/优化的版本,同时允许稍后更改大小/压缩
Deebster 2011年

7

我不确定这是多少“真实世界”示例,但是我目前有一个应用程序可以存储交易卡游戏的详细信息,包括卡的图像。迄今为止,数据库的记录数仅为2851条,但是考虑到某些卡片已被多次释放并具有备用图稿,因此在尺寸上扫描图稿的“主要方块”然后动态地进行扫描实际上更为有效。根据要求生成卡的边框和其他效果。

该图像库的原始创建者创建了一个数据访问类,该类根据请求渲染图像,并且可以非常快速地查看和使用单个卡。

这也简化了发行新卡时的部署/更新,而不是将整个图像文件夹压缩并通过管道发送并确保创建正确的文件夹结构,而是简单地更新数据库并让用户再次下载。目前,该文件的大小最大为56MB,这不是很好,但我正在为将来的发行版开发增量更新功能。此外,该应用程序有一个“无图像”版本,允许那些通过拨号方式获得应用程序的用户不会下载延迟。

迄今为止,该解决方案一直非常有效,因为应用程序本身的目标是在桌面上作为单个实例。有一个网站将所有这些数据存档以供联机访问,但是我绝不会使用相同的解决方案。我同意最好使用文件访问权限,因为它可以更好地扩展对图像的请求的频率和数量。

希望这不会太ba,但我看到了这个话题,并希望从相对成功的中小型应用程序中提供一些见解。


处理复制时,将图像存储在数据库中要比IMO好得多。
发出哔哔声


7

这取决于要存储的图像数量及其大小。我过去曾使用数据库来存储图像,并且我的经验还不错。

IMO,使用数据库存储图像的优点是

A.不需要FS结构来保存图像
B.当要存储更多项目时,数据库索引的性能比FS树更好
。C.智能调优的数据库在缓存查询结果方面表现出色
D.备份很简单。如果已设置复制并且内容是从附近的服务器传递的,则此方法也很好用。在这种情况下,不需要显式同步。

如果您的映像很小(例如<64k),并且数据库的存储引擎支持内联(记录中)BLOB,则由于不需要进行间接调用,因此可以进一步提高性能(实现了引用的局部性)。

当您处理少量的大尺寸图像时,存储图像可能不是一个好主意。在db中存储图像的另一个问题是,创建,修改日期等元数据必须由您的应用程序处理。


7

我最近创建了一个PHP / MySQL应用程序,该程序将PDF / Word文件存储在MySQL表中(到目前为止,每个文件最大40MB)。

优点:

  • 上载的文件将与其他所有文件一起复制到备份服务器,不需要单独的备份策略(请放心)。
  • 设置Web服务器稍微简单一些,因为我不需要上载/文件夹,也不必告诉我所有的应用程序在哪里。
  • 我可以使用事务进行编辑以提高数据完整性-我不必担心孤立和丢失的文件

缺点:

  • mysqldump现在花费了很多时间,因为其中一个表中有500MB的文件数据。
  • 与文件系统相比,整体内存/ CPU效率不高

我将我的实施称为成功,它可以满足备份要求并简化项目的布局。对于使用该应用程序的20至30个人而言,该性能很好。


6

以我的经验,我必须管理两种情况:存储在数据库中的图像和存储在db中的文件系统上的图像。

第一种解决方案是数据库中的图像,它在某种程度上“更干净”,因为您的数据访问层将只需要处理数据库对象。但这仅在您必须处理少量数字时才有用。

显然,当您处理二进制大对象时,数据库访问性能正在下降,并且数据库尺寸将增长很多,从而再次导致性能损失……并且通常数据库空间比文件系统空间昂贵得多。

另一方面,在文件系统中存储较大的二进制对象将导致您具有必须同时考虑数据库和文件系统的备份计划,这对于某些系统可能是个问题。

选择文件系统的另一个原因是,当您必须通过第三方访问权限共享图像数据(或声音,视频等)时:目前,我正在开发一个Web应用程序,该应用程序使用必须从“外部”访问的图像我的Web场以一种根本不可能访问数据库以检索二进制数据的方式。因此,有时也有一些设计注意事项将促使您做出选择。

在做出选择时,还请考虑一下,如果在访问二进制对象时必须处理权限和身份验证:当将数据存储在db中时,通常可以较容易地解决这些要求。


4

我曾经从事图像处理应用程序。我们将上传的图像存储在/ images / [今天的日期] / [id号]之类的目录中。但是,我们还从图像中提取了元数据(exif数据),并将其与时间戳等一起存储在数据库中。


4

在上一个项目中,我将图像存储在文件系统上,这导致备份,复制和文件系统与数据库不同步的麻烦。

在我的最新项目中,我将图像存储在数据库中,并将其缓存在文件系统中,并且效果很好。到目前为止,我还没有遇到任何问题。


3

其次是关于文件路径的建议。我参与了一些项目,这些项目需要管理大量资产,并且任何直接将内容存储在数据库中的尝试都会长期造成痛苦和沮丧。

关于将它们存储在数据库中,我可以想到的唯一真正的“专业人士”是可能轻松获得单个图像资产。如果没有要使用的文件路径,并且所有图像都直接从数据库中流式传输,则不会有用户发现他们不应访问的文件的危险。

不过,似乎可以通过中间脚本从无法访问Web的文件存储中提取数据来更好地解决。因此,数据库存储并不是真正必要的。


3

俗话说,除非您是数据库供应商,试图证明您的数据库可以做到这一点(例如,微软吹嘘Terraserver在SQL Server中存储海量图像),否则这不是一个好主意。当替代方案-将图像存储在文件服务器上和数据库中的路径如此简单时,为什么要麻烦呢?Blob领域有点像SUV的越野功能-大多数人不使用它们,那些通常会遇到麻烦的人,然后还有那些人,但仅仅是出于乐趣。


3

将图像存储在数据库中仍然意味着图像数据最终位于文件系统中的某个位置,但是被遮盖了,因此您无法直接访问它。

+ ves:

  • 数据库完整性
  • 它易于管理,因为您不必担心添加或删除图像时保持文件系统同步

-ves:

  • 性能损失-数据库查找通常比文件系统查找慢
  • 您不能直接编辑图像(裁剪,调整大小)

两种方法都是通用且已实践的。看一下优点和缺点。无论哪种方式,您都必须考虑如何克服这些缺点。存储在数据库中通常意味着调整数据库参数并实现某种缓存。使用文件系统要求您找到某种使文件系统+数据库保持同步的方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.