所以我正在使用一个将图像大量存储在数据库中的应用程序。您对此有何看法?我更倾向于将位置存储在文件系统中,而不是将其直接存储在数据库中。
你认为有什么优点/缺点?
我负责一些管理许多 TB 图像的应用程序。我们发现在数据库中存储文件路径是最好的。
有几个问题:
与大多数问题一样,它并不像听起来那么简单。在某些情况下,将图像存储在数据库中是有意义的。
另一方面也存在相关问题
文件存储。Facebook 工程师对此进行了精彩的讨论。一个收获是了解目录中文件的实际限制。
这可能有点远,但如果您正在使用(或计划使用)SQL Server 2008,我建议您查看新的FileStream数据类型。
FileStream 解决了在数据库中存储文件的大部分问题:
但是 SQL 的“透明数据加密”不会加密 FileStream 对象,因此如果考虑到这一点,最好将它们存储为 varbinary。
来自 MSDN 文章:
Transact-SQL 语句可以插入、更新、查询、搜索和备份 FILESTREAM 数据。Win32 文件系统接口提供对数据的流式访问。
FILESTREAM 使用 NT 系统缓存来缓存文件数据。这有助于减少 FILESTREAM 数据可能对数据库引擎性能产生的任何影响。未使用 SQL Server 缓冲池;因此,该内存可用于查询处理。
数据库中的文件路径绝对是要走的路——我从拥有 TB 图像的客户那里听到一个又一个故事,说试图在数据库中存储大量图像成为一场噩梦——仅对性能造成的影响就太大了。
根据我的经验,有时最简单的解决方案是根据主键命名图像。因此很容易找到属于特定记录的图像,反之亦然。但与此同时,您没有在数据库中存储有关图像的任何内容。
这里的诀窍是不要成为狂热者。
这里需要注意的一点是,专业文件系统阵营中没有人列出特定的文件系统。这是否意味着从 FAT16 到 ZFS 的所有内容都能轻松击败所有数据库?
不。
事实是,即使我们只谈论原始速度,许多数据库也胜过许多文件系统。
正确的做法是为您的精确场景做出正确的决定,为此,您需要一些数字和一些用例估计。
在必须保证参照完整性和 ACID 合规性的地方,需要将图像存储在数据库中。
您不能事务性地保证存储在数据库中的图像和有关该图像的元数据引用同一个文件。换句话说,不可能保证文件系统上的文件只在与元数据相同的时间和相同的事务中被更改。
正如其他人所说,SQL 2008 带有一个 Filestream 类型,它允许您将文件名或标识符作为指针存储在数据库中,并自动将图像存储在文件系统上,这是一个很好的场景。
如果您使用的是较旧的数据库,那么我会说,如果您将其存储为 blob 数据,那么您实际上不会以搜索功能的方式从数据库中获取任何内容,因此这可能是最好的在文件系统上存储地址,并以这种方式存储图像。
这样,您还可以节省文件系统上的空间,因为您只会节省确切的空间量,甚至是文件系统上的压缩空间。
此外,您可以决定保存一些结构或元素,使您可以浏览文件系统中的原始图像而没有任何 db 命中,或者将文件批量传输到另一个系统、硬盘驱动器、S3 或其他场景 - 更新位置你的程序,但保持结构,在尝试增加存储时尝试将图像从数据库中取出并没有太大影响。
可能,它还允许您根据通常点击的图像 url 将一些缓存元素放入您的 Web 引擎/程序中,因此您也可以将自己保存在那里。
不经常编辑的小型静态图像(不超过几兆)应存储在数据库中。这种方法有几个好处,包括更容易移植(图像与数据库一起传输)、更容易备份/恢复(图像与数据库一起备份)和更好的可伸缩性(包含数千个小缩略图文件的文件系统文件夹听起来像是可伸缩性的噩梦)我)。
从数据库提供图像很容易,只需实现一个 http 处理程序,它将从 DB 服务器返回的字节数组作为二进制流提供服务。
这是关于该主题的有趣白皮书。
To BLOB or Not To BLOB:数据库或文件系统中的大对象存储
答案是“视情况而定”。当然,这将取决于数据库服务器及其对 blob 存储的方法。它还取决于存储在 blob 中的数据类型,以及如何访问该数据。
使用数据库作为存储机制,可以有效地存储和传递较小的文件。较大的文件可能最好使用文件系统存储,特别是如果它们会经常修改/更新。(blob 碎片成为性能方面的一个问题。)
这里还有一点需要牢记。支持使用数据库存储 blob 的原因之一是 ACID 合规性。然而,测试人员在白皮书中使用的方法(SQL Server 的 Bulk Logged 选项)使 SQL Server 吞吐量翻了一番,有效地将 ACID 中的“D”更改为“d”,因为 Blob 数据没有被记录事务的初始写入。因此,如果完全符合 ACID 是您的系统的一项重要要求,则在将文件 I/O 与数据库 blob I/O 进行比较时,将数据库写入的 SQL Server 吞吐量数据减半。
我还没有看到有人提到但绝对值得注意的一件事是,在大多数文件系统中也存在与存储大量图像相关的问题。例如,如果您采用上述方法并在主键后命名每个图像文件,那么在大多数文件系统上,如果您尝试将所有图像放在一个大目录中,一旦您获得大量图像(例如数十万或数百万)。
曾经常见的解决方案是将它们散列到平衡的子目录树中。
没有人提到的是数据库保证原子操作、事务完整性和并发处理。即使是文件系统的引用完整性也不存在 - 那么你怎么知道你的文件名真的仍然正确?
如果您将图像保存在文件系统中,并且在您编写新版本甚至删除文件时有人正在读取该文件 - 会发生什么?
我们使用 blob 是因为它们也更易于管理(备份、复制、传输)。他们为我们工作得很好。
在数据库中仅存储图像的文件路径的问题是不能再强制数据库的完整性。
如果文件路径指向的实际图像不可用,则数据库会无意中出现完整性错误。
鉴于图像是正在寻找的实际数据,并且可以在一个集成数据库中更轻松地管理它们(图像不会突然消失),而不必与某种文件系统交互(如果文件系统是独立访问的,图像可能会突然“消失”),我会直接将它们存储为 BLOB 等。
在我以前工作的一家公司,我们在 Oracle 8i(当时是 9i)数据库中存储了 1.55 亿张图像。价值 7.5TB。
通常,我强烈反对采用最昂贵和最难扩展的基础架构(数据库)部分并将所有负载放入其中。另一方面:它极大地简化了备份策略,尤其是当您有多个 Web 服务器并且需要以某种方式保持数据同步时。
像大多数其他事情一样,这取决于预期的规模和预算。
我们已经实现了一个文档图像系统,它将所有图像存储在 SQL2005 blob 字段中。目前有数百 GB,我们看到出色的响应时间和很少或没有性能下降。此外,为了符合法规,我们有一个中间件层,可以将新发布的文档存档到光学点唱机系统,该系统将它们公开为标准的 NTFS 文件系统。
我们对结果非常满意,特别是在以下方面:
如果这是基于 Web 的应用程序,那么将图像存储在第三方存储交付网络上可能会有优势,例如 Amazon 的 S3 或 Nirvanix 平台。
假设:应用程序支持网络/基于网络
我很惊讶没有人真正提到这一点......将其委托给其他专家 ->使用 3rd 方图像/文件托管服务提供商。
将您的文件存储在付费在线服务上,例如
该线程解释了为什么您应该使用 3rd 方托管服务提供商。
太值得了。他们有效地存储它。没有带宽从您的服务器上传到客户端请求等。
如果您不在 SQL Server 2008 上并且您有充分的理由将特定图像文件放入数据库中,那么您可以采用“两者”方法并将文件系统用作临时缓存并将数据库用作主存储库.
例如,您的业务逻辑可以在提供图像文件之前检查磁盘上是否存在图像文件,并在必要时从数据库中检索。这为您购买了多个 Web 服务器的功能并减少了同步问题。
我不确定这是一个“真实世界”的例子,但我目前有一个应用程序可以存储交易卡牌游戏的详细信息,包括卡牌的图像。尽管迄今为止数据库的记录数只有 2851 条记录,但考虑到某些卡片已多次发布并具有替代图稿,实际上扫描图稿的“主要正方形”然后动态扫描尺寸更有效请求时为卡片生成边框和杂项效果。
这个图像库的原始创建者创建了一个数据访问类,它根据请求呈现图像,并且对于查看和个人卡片来说它的速度非常快。
这也简化了新卡发布时的部署/更新,而不是压缩整个图像文件夹并将它们发送到管道并确保创建正确的文件夹结构,我只需更新数据库并让用户再次下载它。目前最大大小为 56MB,这不是很好,但我正在为未来版本开发增量更新功能。此外,还有一个“无图像”版本的应用程序,允许那些通过拨号上网的人在没有下载延迟的情况下获取应用程序。
由于应用程序本身被定位为桌面上的单个实例,因此该解决方案迄今为止运行良好。有一个网站,所有这些数据都被存档以供在线访问,但我绝不会为此使用相同的解决方案。我同意文件访问会更可取,因为它可以更好地适应图像请求的频率和数量。
希望这不是胡说八道,但我看到了这个话题,并想从一个相对成功的中小型应用程序中提供一些我的见解。
SQL Server 2008 提供了一个两全其美的解决方案:文件流数据类型。
像普通表一样管理它并拥有文件系统的性能。
It depends on the number of images you are going to store and also their sizes. I have used databases to store images in the past and my experience has been fairly good.
IMO, Pros of using database to store images are,
A. You don't need FS structure to hold your images
B. Database indexes perform better than FS trees when more number of items are to be stored
C. Smartly tuned database perform good job at caching the query results
D. Backups are simple. It also works well if you have replication set up and content is delivered from a server near to user. In such cases, explicit synchronization is not required.
If your images are going to be small (say < 64k) and the storage engine of your db supports inline (in record) BLOBs, it improves performance further as no indirection is required (Locality of reference is achieved).
Storing images may be a bad idea when you are dealing with small number of huge sized images. Another problem with storing images in db is that, metadata like creation, modification dates must handled by your application.
我最近创建了一个 PHP/MySQL 应用程序,它将 PDF/Word 文件存储在 MySQL 表中(目前每个文件最大 40MB)。
优点:
缺点:
我认为我的实现是成功的,它处理了备份需求并简化了项目的布局。对于使用该应用程序的 20-30 人来说,性能很好。
我的经验是我必须管理这两种情况:存储在数据库中的图像和文件系统上的图像,路径存储在 db 中。
第一个解决方案,数据库中的图像,有点“干净”,因为您的数据访问层只需要处理数据库对象;但这仅在您必须处理低数字时才有用。
显然,当您处理二进制大对象时,数据库访问性能正在下降,并且数据库维度会增长很多,再次造成性能损失......而且通常数据库空间比文件系统空间昂贵得多。
另一方面,将大型二进制对象存储在文件系统中会导致您的备份计划必须同时考虑数据库和文件系统,这对于某些系统来说可能是一个问题。
选择文件系统的另一个原因是当您必须与第三方访问共享您的图像数据(或声音、视频等)时:现在我正在开发一个 Web 应用程序,该应用程序使用必须从“外部”访问的图像“我的网络农场以这样的方式访问数据库来检索二进制数据是根本不可能的。因此,有时还有一些设计因素会促使您做出选择。
还请考虑,在做出此选择时,如果您在访问二进制对象时必须处理权限和身份验证:当数据存储在 db 中时,这些要求通常可以以更简单的方式解决。
我曾经做过一个图像处理应用程序。我们将上传的图像存储在类似于 /images/[今天的日期]/[id 编号] 的目录中。但是我们还从图像中提取了元数据(exif 数据)并将其与时间戳等一起存储在数据库中。
在之前的一个项目中,我将图像存储在文件系统上,这给备份、复制和文件系统与数据库不同步带来了很多麻烦。
在我最新的项目中,我将图像存储在数据库中,并将它们缓存在文件系统中,并且效果非常好。到目前为止,我没有遇到任何问题。
其次是关于文件路径的建议。我参与了几个需要管理大型资产集合的项目,任何将事物直接存储在数据库中的尝试都会导致长期的痛苦和挫败感。
关于将它们存储在数据库中,我能想到的唯一真正的“专业人士”是易于使用单个图像资产的潜力。如果没有文件路径可供使用,并且所有图像都直接从数据库中流出,那么用户就不会发现他们不应该访问的文件的危险。
不过,这似乎可以通过从 Web 无法访问的文件存储中提取数据的中间脚本来更好地解决。所以数据库存储并不是真正需要的。
流行的说法是,除非您是试图证明您的数据库可以做到这一点的数据库供应商(例如,假设 Microsoft 吹嘘 Terraserver 在 SQL Server 中存储了 bajillion 图像),否则这不是一个好主意。当替代方案 - 将图像存储在文件服务器和数据库中的路径变得如此容易时,为什么还要麻烦呢?Blob 字段有点像 SUV 的越野能力——大多数人不使用它们,那些使用它们的人通常会遇到麻烦,然后有些人会使用它们,但只是为了好玩。
将图像存储在数据库中仍然意味着图像数据最终会存储在文件系统中的某个位置,但会被隐藏,因此您无法直接访问它。
+ves:
-ves:
这两种方法都很常见,也很实用。看看优点和缺点。无论哪种方式,您都必须考虑如何克服缺点。存储在数据库中通常意味着调整数据库参数并实现某种缓存。使用文件系统需要您找到某种方法来保持文件系统+数据库同步。
我是企业文档管理系统的首席开发人员,一些客户在该系统中存储了数百 GB 的文档。TB 在不久的将来。我们使用文件系统方法是出于本页中提到的许多原因以及另一个原因:归档。
我们的许多客户必须遵守行业特定的归档规则,例如存储到光盘或以非专有格式存储。此外,您还可以灵活地将更多磁盘添加到 NAS 设备。如果您将文件存储在数据库中,即使使用 SQL Server 2008 的文件流数据类型,您的归档选项也会变得非常狭窄。
如果您需要在文件系统上存储大量图像,需要考虑以下几点:
您的网络服务器(我假设您使用的是一个)旨在处理图像,而数据库则不是。因此,我会大力投反对票。
只在数据库中存储路径(也可能是文件信息)。
我会亲自将大数据存储在数据库之外。
优点:将所有内容存储在一个文件中,易于访问数据文件,易于备份缺点:降低数据库性能,许多页面拆分,可能的数据库损坏
我们将图像存储在表中的唯一原因是因为每个表(或每个工作范围的表集)都是临时的,并且在工作流结束时被删除。如果有任何形式的长期存储,我们肯定会选择存储文件路径。
还应该注意的是,我们在内部使用客户端/服务器应用程序,因此无需担心 Web 界面。
正如有人已经提到的那样,“这取决于”。如果数据库中的存储应该是文件系统的一对一精美替代品,那么它可能不是一个最佳选择。
但是,如果数据库后端将提供额外的值,而不仅仅是对 blob 的序列化和存储,那么它可能会真正有意义。
您可以查看WKT Raster,这是一个旨在在PostGIS中开发栅格支持的项目,后者又用作PostgreSQL数据库系统的地理空间扩展。WKT Raster 背后的想法不仅是定义栅格序列化和存储的格式(使用 PostgreSQL 系统),而且比存储更重要的是指定可从 SQL 访问的数据库端高效图像处理。长话短说,这个想法是将操作权重从客户端转移到数据库后端,因此它尽可能靠近存储本身。WKT 栅格作为 PostGIS,专用于特定领域GIS的应用。
通过网络从数据库中提取大量二进制数据会导致巨大的延迟问题,并且无法很好地扩展。
在数据库中存储路径并让您的网络服务器承担负载 - 这就是它的设计目的!
尝试使用 SQL 模拟文件系统通常是一个糟糕的计划。如果您坚持使用文件系统作为外部存储,您最终会编写更少的代码并获得相同或更好的结果。
File system, for sure. Then you get to use all of the OS functionality to deal with these images - back ups, webserver, even just scripting batch changes using tools like imagemagic. If you store them in the DB then you'll need to write your own code to solve these problems.
我会采用文件系统方法,主要是因为它具有更好的灵活性。考虑到如果图像数量变得巨大,一个数据库可能无法处理它。使用文件系统,您可以简单地添加更多文件服务器,假设您使用的是 NFS 或 kind。
文件系统方法的另一个优点是能够做一些花哨的事情,例如您可以使用 Amazon S3 作为主存储(将 url 保存在数据库中而不是文件路径中)。如果 S3 发生中断,您将回退到您的文件服务器(可能是另一个包含文件路径的数据库条目)。适用于 Apache 或您正在使用的任何 Web 服务器的一些巫术。
我更喜欢将图像路径存储在数据库中,并将图像存储在文件系统上(在服务器之间使用 rsync 以使所有内容保持合理的最新状态)。
然而,我做的一些内容管理系统的东西需要 CMS 中的图像有几个原因 - 可见性控制(因此资产被保留直到新闻稿发布)、版本控制、重新格式化(一些 CMS 将动态调整大小缩略图)和易于使用的图像链接到所见即所得的页面。
所以我的经验法则是始终将应用程序的东西存储在文件系统上,除非它是由 CMS 驱动的。
您需要记住的一件事是数据集的大小。我相信 Dillie-O 是唯一一个甚至遥不可及的人。
如果您有一个小型的单用户消费者应用程序,那么我会说 DB。我有一个使用文件系统(在 Program Files 中)的 DVD 管理应用程序,它是一个要备份的 PIA。我希望他们每次都将它们存储在数据库中,并让我选择保存该文件的位置。
对于更大的商业应用程序,我会开始改变我的想法。我曾经在一家开发县文员信息管理应用程序的公司工作。我们将根据县分配的仪器编号以编码格式[以处理大量文件的 FS 问题] 将图像存储在磁盘上。这在另一个方面很有用,因为图像可能存在于数据库记录之前(由于他们的工作流程)。
与大多数事情一样:“这取决于你在做什么”
将图像存储在文件系统中的另一个好处是您无需执行任何特殊操作即可让客户端缓存它们...
...当然,除非图像不能通过文档根目录访问(例如身份验证屏障),在这种情况下,您需要检查代码发送的缓存控制标头。
I would go with the file system approach. No need to create or maintain a DB with images, it will save you some major headaches in the long run.
我几乎从不将它们存储在数据库中。最好的方法通常是将图像存储在由中央配置变量控制的路径中,并根据数据库表和主键(如果可能)命名图像。这为您带来以下优势:
数据数据库
文件的文件系统
我会选择这两种解决方案,我的意思是......我将开发一个小组件(EJB),将图像存储在数据库中,并将该图像的路径存储到服务器中。仅当我们有新图像或已更新的原始图像时,才会更新此数据库。然后我还将路径存储在业务数据库中。
从应用程序的角度来看,我将始终使用文件系统(从业务数据库中检索路径),通过这种方式我们将解决备份问题,并避免可能的性能问题。
唯一的缺点是我们将存储相同的图像 2 次......好处是内存很便宜,加油!
对于大量的小图像,数据库可能会更好。
我有一个带有许多小缩略图(每个 2Kb)的应用程序。当我将它们放在文件系统上时,由于文件系统的块大小,它们每个消耗 8kb。空间增加 400%!
有关块大小的更多信息,请参阅这篇文章: iphone 文件系统的块大小是多少?
如果您在 Teradata 上,那么 Teradata Developer Exchange 有一篇关于加载和检索 lob 和 blob 的详细文章。
http://developer.teradata.com/applications/articles/large-objects-part-1-loading
我使用过许多数字存储系统,它们都将数字对象存储在文件系统上。他们倾向于使用分支方法,因此文件系统上会有一个存档树,通常从条目年份开始,例如 2009,子目录将是月份,例如八月的 8,下一个目录将是一天,例如 11,有时他们会使用小时,然后文件将使用记录持久 ID 命名。使用 BLOBS 有其优势,我听说它经常用于化工行业的 IT 部分,用于存储数千或数百万张照片和图表。它可以提供更细粒度的安全性、单一的备份方法、可能更好的数据完整性和改进的媒体间搜索,Oracle 在他们过去称为 Intermedia 的包中为此提供了许多功能(我认为它现在被称为其他东西)。文件系统还可以通过诸如 XACML 或其他 XML 类型安全对象的系统提供细粒度的安全性。有关示例,请参见 Fedora 对象存储的 D 空间。
文件存储中的图像是最好的选择,并将元数据存储在数据库中作为补充。从 Web 服务器的角度来看,提供内容的快速方法是直接指向它。如果它在数据库中 - ala Sharepoint - 您需要 ADO.Net 的开销来将其拉出、流式传输等。
Documentum - 虽然臃肿且复杂 - 其正确之处在于文件在共享中,可供您确定如何存储它们 - 服务器上的磁盘、SAN、NAS 等等。Documentum 策略是通过根据数据库中的主键对文件夹和文件名进行编码,将文件存储为树结构。数据库成为了解哪些文件是什么并加强安全性的资源。对于大容量系统,这种方法是一个不错的方法。
在处理元数据时还要考虑这一点:如果您需要更新元数据语料库的属性,数据库是您的朋友,因为您可以使用 SQL 快速执行更新。使用其他标记系统,您手头没有简单的数据操作工具
不,由于页面拆分。您实际上是在定义可以为 1KB - n MB 的行,因此您的数据库将在其页面中有很多空白空间,这对性能不利。
在我的小应用程序中,我至少有一百万个文件,最后一次计数大约为 200GB。所有文件都位于通过 iscsi 安装在 linux 服务器上的 XFS 文件系统中。路径存储在数据库中。对文件路径和文件名使用某种智能命名约定。
恕我直言,将文件系统用于它的目的 - 存储文件。与标准文件系统相比,数据库在存储二进制数据方面通常不会为您提供任何优势。
我会采用文件系统方法。正如其他一些人所指出的,大多数 Web 服务器都是为从文件路径发送图像而构建的。如果您不必从数据库中写入或流出 BLOB 字段,您将获得更高的性能。为图像提供文件系统存储可以在内容不变或您希望限制数据库负载时更轻松地设置静态页面。
在我当前的应用程序中,我正在做这两个。当用户确定要附加到记录的图像时,我使用 ImageMagick 将其调整为适当的大小以在屏幕上显示(我的应用程序约为 300x300)并将其存储在数据库中以便于访问,但随后也复制用户的原始文件到网络共享,以便它可用于需要更高分辨率的应用程序(如打印)。
(还涉及到其他几个因素:Navision 只会显示 BMP,所以当我调整它的大小时,我也会转换为 BMP 进行存储,并且数据库会复制到远程站点,以便能够显示图像。打印只在总公司做,所以我不需要复制原始文件。)
如果您正在计划一个面向公众的网站,那么您不应该选择任何一个选项。您应该使用内容交付网络 (CDN)。当通过 Internet 提供大量静态内容时,CDN 具有价格、可扩展性和速度优势。