在DB中存储图像 - 是还是不?

Jam*_*all 415 database theory storage blob image

所以我正在使用一个将图像存储在数据库中的应用程序.你对此有何看法?我更像是一种在文件系统中存储位置的类型,而不是直接将它存储在数据库中.

您认为利弊是什么?

Mar*_*son 350

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

有几个问题:

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

  • 什么现成的产品可用于"超级加速"文件系统? (33认同)
  • 虽然我只管理3TB的文件,但我绝对同意.数据库用于结构化数据,而不是blob. (22认同)
  • 什么现成的产品可用于"超级加速"文件系统? (14认同)
  • @derobert:非常好,如果您永远不会在查询中使用数据元素,作为条件或连接,它可能不属于数据库.再说一遍,如果你有一个很好的数据库函数来查询图像的相似性...... (7认同)
  • Re:"超级加速"产品:大多数Web服务器现在可以利用sendfile()系统调用来异步地向客户端提供静态文件.它将文件从磁盘移动到网络接口的任务卸载到操作系统.在内核空间中运行时,操作系统可以更有效地执行此操作.对我来说,对于存储/提供图像,这对于文件系统与数据库来说似乎是一个巨大的胜利. (5认同)
  • 重新"超级加速":我正在考虑诸如isilon,emc,netapp等产品,它们可以配置为存储在文件系统中的集群,缓存等数据(在我们的例子中是NFS).这是我做的一个演讲,讨论了一些问题.它是在一次perforce会议上,因此它没有详细介绍数据库方面,但它涵盖了我们所做工作的要点:http://maillist.perforce.com/perforce/conferences/us/2009/index.html #pixar (3认同)
  • 它也是文件系统上最有用的存储图像.试想一下,如果客户打电话询问他们无法查看图片,但他们有图像ID.更快地定位和查看文件系统上的映像而不是数据库(代码可能存在问题). (2认同)

Rad*_*Rad 140

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

  • 您正在存储动态变化的图像,比如发票,而您想获得2007年1月1日的发票?
  • 政府希望你保持6年的历史
  • 存储在数据库中的图像不需要不同的备份策略.存储在文件系统上的图像可以
  • 如果图像位于数据库中,则更容易控制对图像的访问.空闲管理员可以访问磁盘上的任何文件夹.需要一个真正确定的管理员才能在数据库中窥探以提取图像

另一方面,存在相关问题

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

  • 默默无闻的安全性并不是真正的访问控制策略! (44认同)
  • 我不认为他是默默无闻地提倡安全 - 他说将图像放入数据库会增加另一层安全性.(我想...... @Conrad,不想把话放在嘴里) (5认同)
  • 当您编写内部安装的应用程序(如SharePoint)时,没有单独的备份策略可能是一个大问题.当您创建SharePoint备份时,所有内容都在数据库中,这使得它非常容易. (2认同)

jas*_*ldo 99

文件存储.Facebook工程师对它进行了很好的讨论.一个要点是了解目录中文件的实际限制.

大海捞针:高效存储数十亿张照片


Ray*_*Ray 56

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

FileStream解决了将文件存储在数据库中的大部分问题:

  1. Blob实际上存储为文件夹中的文件.
  2. 该斑点可使用被访问或者数据库连接在文件系统中.
  3. 备份是集成的.
  4. 迁移"正常".

但是,SQL的"透明数据加密"不会加密FileStream对象,所以如果这是一个考虑因素,最好只将它们存储为varbinary.

来自MSDN文章:

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


Gre*_*man 39

数据库中的文件路径绝对可行的方法 - 我听说过来自有TB图像的客户的故事,它变成了一个噩梦,试图在数据库中存储任何大量的图像 - 单独的性能影响太大了.


Pat*_*ney 35

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

  • @Marijn:只有当你把图像暴露给世界时才会这样. (6认同)

dic*_*oce 31

这里的诀窍是不要成为狂热者.

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

没有.

事实上,许多数据库都击败了许多文件系统,即使我们只讨论原始速度.

正确的做法是为您的确切方案做出正确的决定,为此,您需要一些数字和一些用例估算.

  • 我没有看到有人声称文件系统100%的速度比DB更快(阅读Mark Harrison的回答).那是一个稻草人.在某种情况下,最好不要系安全带,但一般来说,系好安全带是一个好主意. (6认同)

mlu*_*bke 30

在必须保证参照完整性和ACID合规性的地方,需要在数据库中存储图像.

您不能事务性地保证图像和存储在数据库中的该图像的元数据引用相同的文件.换句话说,不可能保证文件系统上的文件只在与元数据同时和相同的事务中被改变.

  • 实际上,不,你可以.只要图像文件永远不会被删除,更改或覆盖一旦创建,所有图像文件在尝试提交事务之前都会同步,没有文件系统损坏,您可以确保图像文件和元数据是同步的.对于某些应用程序,我猜这些应用程序太多了. (7认同)

cru*_*ble 28

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

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

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

此外,您可以决定使用某些结构或元素进行保存,这些结构或元素允许您浏览文件系统中的原始图像而无需任何数据库命中,或者将文件批量传输到另一个系统,硬盘驱动器,S3或其他方案 - 更新位置你的程序,但保持结构,再次尝试增加存储时尝试将图像从数据库中删除.

也许,它还允许你根据常用的图像网址将一些缓存元素添加到你的web引擎/程序中,这样你就可以将自己保存在那里.


uri*_*ini 27

不经常编辑的小静态图像(不超过几个megs)应存储在数据库中.这种方法有几个好处,包括更容易移植(图像与数据库一起传输),更容易备份/恢复(图像备份数据库)和更好的可扩展性(一个包含数千个小缩略图文件的文件系统文件夹听起来像一个可扩展性的噩梦我).

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


小智 26

这是一篇关于这个主题的有趣的白皮书.

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

答案是"这取决于".当然,这取决于数据库服务器及其blob存储方法.它还取决于存储在blob中的数据类型,以及如何访问这些数据.

使用数据库作为存储机制,可以有效地存储和传送较小尺寸的文件.较大的文件可能最好使用文件系统存储,特别是如果它们经常被修改/更新.(blob碎片成为性能方面的问题.)

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


Joh*_*ohn 25

我还没有看到有人提到的一件事,但绝对值得注意的是,在大多数文件系统中存储大量图像也存在问题.例如,如果您采用上述方法并在主键之后命名每个图像文件,则在大多数文件系统上,如果在达到大量图像时尝试将所有图像放在一个大目录中,则会遇到问题(例如,数十万或数百万).

一般的解决方案是将它们散列到一个平衡的子目录树中.

  • 我有一个应用程序在一个目录(运行RHEL 4的服务器)中有数百万个文件 - 甚至列出目录内容(管道到文件)需要几天时间,并创建了100个MB大小的输出文件.现在他们在一个数据库中我有一个文件,我可以很容易地移动或备份. (8认同)

Dra*_*mon 22

没有人提到的是DB保证原子操作,事务完整性和处理并发.即使引用完整性也不在文件系统的窗口 - 所以你怎么知道你的文件名真的是正确的?

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

我们使用blob因为它们更容易管理(备份,复制,传输).它们对我们很有用.


wis*_*guy 20

仅将文件路径存储到数据库中的映像的问题是不再强制数据库的完整性.

如果文件路径指向的实际图像变得不可用,则数据库无意中会出现完整性错误.

鉴于图像是正在寻找的实际数据,并且它们可以在一个集成数据库中更容易管理(图像不会突然消失),而不必与某种文件系统接口(如果文件系统是独立访问的,图像MIGHT突然"消失"),我会直接将它们存储为BLOB等.


gra*_*eds 17

在我以前工作的公司,我们在Oracle 8i(当时的9i)数据库中存储了1.55亿个图像.7.5TB值得.

  • 绝对.显然,数据库现在要大得多.将数据放在数据库中意味着在不同站点复制数据库也更容易. (5认同)

Mic*_*tum 14

通常情况下,我坚决反对花费最贵和最难扩展部分基础设施(数据库)并将所有负载放入其中.另一方面:它极大地简化了备份策略,特别是当您有多个Web服务器并且需要以某种方式保持数据同步时.

像大多数其他东西一样,它取决于预期的大小和预算.


dan*_*266 13

我们已经实现了一个文档成像系统,它将所有图像存储在SQL2005 blob字段中.目前有几百GB,我们看到了出色的响应时间,很少或没有性能下降.此外,在法规遵从性方面,我们有一个中间件层,可将新发布的文档存档到光学点唱机系统,该系统将它们作为标准NTFS文件系统公开.

我们对结果非常满意,特别是在以下方面:

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


Dav*_*vid 11

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


Pur*_*ome 11

假设:应用程序是基于Web的/基于Web的

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

将您的文件存储在付费在线服务上

另一个StackOverflow线程在这里谈论这个.

此主题解释了为什么您应该使用第三方托管服务提供商.

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


a7d*_*rew 10

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

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


Dil*_*e-O 7

我不确定这是一个"现实世界"的例子,但我目前有一个应用程序存储交易卡游戏的详细信息,包括卡片的图像.虽然迄今为止数据库的记录数仅为2851条记录,但考虑到某些卡已多次发布并具有替代图形,实际上扫描图形的"主要方块"然后动态更有效.在请求时为卡片生成边框和杂项效果.

此图像库的原始创建者创建了一个数据访问类,该类根据请求呈现图像,并且它可以非常快速地查看和单个卡.

这也可以在发布新卡时简化部署/更新,而不是压缩整个图像文件夹并将其发送到管道并确保创建正确的文件夹结构,我只需更新数据库并让用户再次下载它.目前这个大小高达56MB,这不是很好,但我正在为未来版本开发增量更新功能.此外,还有一个"无图像"版本的应用程序,允许那些通过拨号获得应用程序而没有下载延迟.

此解决方案迄今为止运行良好,因为应用程序本身作为桌面上的单个实例.有一个网站可以存档所有这些数据以供在线访问,但我绝不会使用相同的解决方案.我同意文件访问会更好,因为它可以更好地扩展到为图像提出的请求的频率和数量.

希望这不是太多喋喋不休,但我看到了这个主题,并希望从相对成功的中小规模应用程序中提供一些我的见解.


And*_*nea 7

SQL Server 2008提供了两全其美的解决方案:文件流数据类型.

像常规表一样管理它并具有文件系统的性能.


小智 7

这取决于您要存储的图像数量以及它们的大小.我过去曾使用数据库来存储图像,而且我的经验相当不错.

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

A.您不需要FS结构来保存图像
B.当要存储更多项目时,数据库索引的性能优于FS树
C.智能调整的数据库在缓存查询结果方面表现良好
D.备份很简单.如果您具有复制设置并且内容从靠近用户的服务器传送,它也可以很好地工作.在这种情况下,不需要显式同步.

如果您的映像将很小(比如<64k)并且数据库的存储引擎支持内联(记录中)BLOB,则它会进一步提高性能,因为不需要间接(实现了引用的位置).

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


too*_*php 7

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

优点:

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

缺点:

  • mysqldump现在占用了很长的时间,因为其中一个表中有500MB的文件数据.
  • 总的来说,与文件系统相比,内存/ CPU效率并不高

我称我的实现成功,它负责备份要求并简化项目的布局.对于使用该应用程序的20-30人来说,性能很好.


ila*_*ila 6

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

第一个解决方案,即数据库中的图像,有点"干净",因为您的数据访问层必须只处理数据库对象; 但只有当你必须处理低数字时,这才是好的.

显然,处理二进制大对象时的数据库访问性能会降低,并且数据库维度会增长很多,导致性能再次降低......通常数据库空间比文件系统空间贵得多.

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

进入文件系统的另一个原因是,当您必须与第三方访问共享您的图像数据(或声音,视频等)时:在这几天我正在开发一个使用必须从"外部"访问的图像的Web应用程序"我的网络农场以这样一种方式,数据库访问来检索二进制数据根本不可能.因此,有时也会有一些设计考虑因素可以帮助您做出选择.

在进行此选择时,还要考虑在访问二进制对象时是否必须处理权限和身份验证:当数据存储在db中时,这些必需品通常可以更容易地解决.