提问



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


您认为利弊是什么?

最佳参考


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


有几个问题:



  • 数据库存储通常比文件系统存储更昂贵

  • 您可以使用标准的现成产品超级加速文件系统访问


    • 例如,许多Web服务器使用操作系统的 sendfile()系统调用将文件直接从文件系统异步发送到网络接口。存储在数据库中的图像不会受益于此优化。


  • 诸如Web服务器之类的东西,不需要特殊的编码或处理来访问文件系统中的图像

  • 数据库赢得了图像和元数据之间的事务完整性很重要的地方。


    • 管理数据库元数据和文件系统数据之间的完整性更为复杂

    • 很难(在Web应用程序的上下文中)保证数据已刷新到文件系统上的磁盘



其它参考1


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



  • 您正在存储的图像
    动态变化,说发票和你想要的
    获得1月1日的发票
    2007?

  • 政府希望你保持6年的历史

  • 存储在数据库中的图像不需要不同的备份策略。存储在文件系统上的图像

  • 如果图像位于数据库中,则更容易控制对图像的访问。空闲管理员可以访问磁盘上的任何文件夹。需要一个真正确定的管理员才能在数据库中窥探以提取图像



另一方面,存在相关问题



  • 需要提取其他代码
    并流式传输图像

  • 延迟可能是
        比直接文件访问慢

  • 数据库服务器上的负载更重


其它参考2


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


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

其它参考3


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


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



  1. Blob实际上存储为文件夹中的文件。

  2. 可以使用 数据库连接或通过文件系统访问Blob。

  3. 备份已集成。

  4. 迁移正常。



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


来自MSDN文章:



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


其它参考4


数据库中的文件路径是肯定的方式 - 我已经听说过来自有TB图像的客户的故事,它变成了一个噩梦,试图在数据库中存储任何大量的图像 - 单独的性能打击太多了。

其它参考5


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

其它参考6


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


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


没有。


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


正确的行动方案是为您的确切方案做出正确的决定,并且为此,您将需要一些数字和一些用例估计。

其它参考7


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


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

其它参考8


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


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


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


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


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

其它参考9


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


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

其它参考10


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


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


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


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


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

其它参考11


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


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

其它参考12


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


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


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

其它参考13


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


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


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

其它参考14


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

其它参考15


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


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

其它参考16


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


我们对结果非常满意,特别是对于:



  1. 易于复制和备份

  2. 能够轻松实现文档版本控制系统


其它参考17


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

其它参考18


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


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


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



  • Amazon S3

  • Moso Cloud Storage



另一个StackOverflow线程在这里谈论这个。[4] [5]


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


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

其它参考19


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


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

其它参考20


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


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


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


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


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

其它参考21


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


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

其它参考22


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


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


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


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


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

其它参考23


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


优点:



  • 上传的文件与其他所有文件一起复制到备份服务器,不需要单独的备份策略(安心)。

  • 设置网络服务器稍微简单一点,因为我不需要上传/文件夹,并告诉我所有的应用程序它在哪里。

  • 我使用事务进行编辑以提高数据完整性 - 我不必担心孤立和丢失文件



缺点:



  • mysqldump现在花了很多时间,因为其中一个表中有500MB的文件数据。

  • 与文件系统
  • 相比,整体上没有非常高的内存/CPU效率


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

其它参考24


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


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


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


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


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


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

其它参考25


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

其它参考26


在之前的项目中,我将图像存储在文件系统上,这导致了许多令人头疼的事情,包括备份,复制和文件系统与数据库不同步。


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

其它参考27


其次是文件路径的建议。我曾经处理过几个需要管理大型资产收集的项目,任何直接在数据库中存储事物的尝试都会导致长期的痛苦和挫折。


关于将它们存储在数据库中,我能想到的唯一真正的专业是单个图像资产的易用性。如果没有文件路径可供使用,并且所有图像都直接从数据库流出,则用户找不到他们无法访问的文件的危险。


这似乎可以通过中间脚本从Web不可访问的文件存储中提取数据来更好地解决。所以数据库存储并不是必需的。

其它参考28


街上的一句话是,除非你是一个数据库供应商试图证明你的数据库可以做到这一点(比如,让我们说微软吹嘘Terraserver在SQL Server中存储了大量的图像),这不是一个好主意。当替代方案 - 在文件服务器上存储图像和数据库中的路径更加容易时,为什么要这么麻烦? Blob领域有点像SUV的越野能力 - 大多数人不会使用它们,那些通常会遇到麻烦的人,然后有些人会这样做,但只是为了它的乐趣。

其它参考29


在数据库中存储图像仍然意味着图像数据最终会在文件系统中的某处结束,但会被遮挡,因此您无法直接访问它。


+ VES:



  • 数据库完整性

  • 易于管理,因为您不必担心在添加或删除图像时保持文件系统同步



-ves:

  • 性能损失 - 数据库查找通常比文件系统查找慢

  • 您无法直接编辑图像(裁剪,调整大小)



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