【问题标题】:To Do or Not to Do: Store Images in a Database [duplicate]做或不做:将图像存储在数据库中[重复]
【发布时间】:2010-10-23 08:55:00
【问题描述】:

在 web 应用程序的上下文中,我的老老板总是说在数据库中放置对图像的引用,而不是图像本身。我倾向于同意将 url 与图像本身存储在数据库中是一个好主意,但是我现在工作的地方,我们在数据库中存储了很多图像。

我能想到的唯一原因可能是它更安全?您不希望有人直接链接到网址吗?但如果是这种情况,您始终可以让网站/服务器处理图像,例如 asp.net 中的处理程序,以便用户需要进行身份验证才能查看图像。我还认为从数据库中提取图像会损害性能。将图像存储在数据库中可能是个好主意/不太好主意的任何其他原因?


完全重复: User Images: Database or filesystem storage?
完全重复: Storing images in database: Yea or nay?
完全重复: Should I store my images in the database or folders?
完全重复:Would you store binary data in database or folders?
完全重复:Store pictures as files or or the database for a web app?
完全重复:Storing a small number of images: blob or fs?
完全重复: store image in filesystem or database?

【问题讨论】:

  • 这个问题问得我数不过来。对这些广泛的问题进行搜索。他们中的大多数人都被问过了。
  • 这个似乎比其他任何一个都有更好的答案,即使它没有受到太多关注。也许其他人应该与这个联系起来?或者合并可能会很好。

标签: database performance blob


【解决方案1】:

将图像放入数据库的优点。

  1. 交易。保存 blob 时,您可以像提交任何其他数据库数据一样提交它。这意味着您可以将 blob 与任何关联元数据一起提交,并确保两者同步。如果磁盘空间不足?没有承诺。文件没有完全上传?没有承诺。愚蠢的应用程序错误?没有承诺。如果保持图像及其相关元数据彼此一致对您的应用程序很重要,那么数据库可以提供的事务可能是一个福音。

  2. 一个系统来管理。需要备份元数据和 blob?备份数据库。需要复制它们吗?复制数据库。需要从部分系统故障中恢复?重新加载数据库并向前滚动日志。 DB 为一般数据带来的所有优势(卷映射、存储控制、备份、复制、恢复等)都适用于您的 blob。一致性更高,管理更轻松。

  3. 安全。数据库具有可以利用的非常细粒度的安全功能。模式、用户角色,甚至诸如“只读视图”之类的东西,以提供对数据子集的安全访问。所有这些功能也适用于保存 blob 的表。

  4. 集中管理。与 #2 相关,但基本上 DBA(好像他们没有足够的权力)可以管理一件事:数据库。现代数据库(尤其是大型数据库)在跨多台机器的大型安装中运行良好。单一管理来源简化了程序,简化了知识转移。

  5. 大多数现代数据库都可以很好地处理 blob。借助数据层中对 blob 的一流支持,您可以轻松地将 blob 从数据库流式传输到客户端。虽然您可以执行一些操作,但会一次性“吸入”整个 blob,但如果您不需要该工具,请不要使用它。研究数据库的 SQL 接口并利用其功能。没有理由将它们视为“大字符串”,它们会被整体处理并将你的 blob 变成大的、内存吞噬、缓存粉碎的炸弹。

  6. 就像您可以为图像设置专用文件服务器一样,您可以在数据库中设置专用 Blob 服务器。给他们专用的磁盘卷、专用的模式、专用的缓存等。数据库中的所有数据都不相同,或者行为相同,没有理由将其配置为完全相同。好的数据库具有良好的控制水平。

从数据库中提供 blob 的首要任务是确保您的 HTTP 层实际上利用所有 HTTP 协议来执行服务。

许多幼稚的实现只是简单地抓取 blob,然后将它们全部倾倒到套接字中。但是 HTTP 有几个非常适合流式传输图像等的重要特性。特别是缓存标头、ETag 和分块传输以允许客户端请求 blob 的“片段”。

确保您的 HTTP 服务正确地处理所有这些请求,并且您的数据库可以成为一个非常好的网络公民。通过将文件缓存在文件系统中以供 HTTP 服务器提供服务,您可以获得“免费”的一些优势(因为一个好的服务器无论如何都会为“静态”资源做到这一点),但请确保如果您这样做,您尊重图像的修改日期等。

例如,有人请求 spaceshuttle.jpg,这是 2009 年 1 月 1 日创建的图像。最终在请求日期(例如 2009 年 2 月 1 日)缓存在文件系统中。随后,该图像从缓存中清除(先进先出政策或其他),然后有人在 2009 年 3 月 1 日再次请求它。好吧,现在它有一个 2009 年 3 月 1 日的“创建日期”,尽管它的创建日期实际上是 1 月 1 日。所以,你可以看到,特别是如果你的缓存经常转,客户端可能正在使用 If-修改后的标头可能会获得比实际需要更多的数据,因为服务器认为资源已更改,而实际上并没有。

如果您将缓存创建日期与实际创建日期保持同步,则问题可能会更小。

但关键是,要想成为“优秀的网络公民”,需要仔细考虑整个问题,并为您和您的客户节省一些带宽等。

我刚刚为一个从数据库提供视频的 Java 项目完成了所有这些工作,这一切都很好。

【讨论】:

  • 请客?是的,大约 100 位观众和十几个视频。
  • 即使我的里程不同,我也不会拒绝这样的详细答案,除非其中存在事实错误。
  • @foljs 他可能只需要 100 个观众。无论如何,我以前见过其他人提出将大数据存储在数据库中的案例,并且他们一直很有说服力,尽管我自己不会这样做。复制有很多好处,也是一种可行的冗余解决方案。我会对 WillHartung 的应用程序获得的视频量和流量感兴趣,因为这听起来很有趣。
  • 还有(因为这个答案大约有 4 年的历史),从那以后他是否改变了主意或方法。
  • 嘿,即使您考虑服务器和客户端的双重负载。我的意思是,如果图像大小为 1 MB,并在远程专用 DBMS 服务器上存储为 blob。现在需要服务器端脚本从远程服务器获取图像(服务器带宽被浪费),现在图像由客户端从服务器下载。
【解决方案2】:

如果您偶尔需要检索图像并且它必须在多个不同的网络服务器上可用。但我认为差不多就是这样。

  • 如果它不必在多台服务器上可用,最好将它们放在文件系统中。
  • 如果它必须在多台服务器上可用,并且系统中确实存在某种负载,则需要某种分布式存储。

我们在这里讨论的是一个边缘案例,在这种情况下,您可以通过利用数据库来避免给您的系统增加额外级别的复杂性。

除此之外,不要这样做。

【讨论】:

  • 如何将这些数据(恰好是一个 blob)存储在数据库中是一种“额外的复杂程度”?其他所有内容都存储在数据库中。实际上,当您迁移在文件系统上存储图像的应用程序时,您还有另一个使迁移复杂化的项目:Web 根目录、数据库、文件系统上的图像。多么痛苦。保持生产和舞台同步怎么样?当一切都在数据库中时很容易做到,但在没有时会更痛苦(你好 rsync 脚本)。
  • @Justin,我根本不是这么说的。再读一遍。我的意思是,在大多数分布式系统中,数据库是唯一的通用存储,因此在这些情况下它实际上可能比部署某种分布式存储更简单。不过,总的来说,我仍然认为这不是一个好主意。
  • 糟糕!我的错。我的立场是正确的。
【解决方案3】:

据我了解,如果您将图像存储在数据库中(甚至提及),大多数数据库专业人员都会对您竖起大拇指并发出嘶嘶声。是的,当使用数据库作为任何类型的大块二进制数据的存储库时,肯定会影响性能和存储(图像往往是最常见的无法标准化的数据位)。但是,在大多数情况下,图像的数据库存储不仅是允许的,而且是可取的

例如,在我以前的工作中,我们有一个应用程序,用户可以在其中将图像附加到他们正在编写的报告的几个不同点,并且必须在完成后打印出这些图像。这些报告是通过 SQL Server 复制移动的,如果尝试以任何可靠性跨多个系统和服务器管理这些图像和文件路径,将会带来巨大的麻烦。将它们存储在数据库中为我们“免费”提供了所有这些功能,并且报告工具不必进入文件系统来检索图像。

【讨论】:

    【解决方案4】:

    我的一般建议是不要将自己局限于一种方法或另一种方法 - 使用适合情况的技术。文件系统非常擅长存储文件,而数据库非常擅长根据请求提供一口大小的数据块。另一方面,我公司的一个产品要求将应用程序的整个状态存储在数据库中,这意味着文件附件也会存储在数据库中。使用我们的数据库服务器 (SQL Server 2005),即使是大型客户和数据库,我也没有遇到明显的性能问题。

    Microsoft 的 SQL 2008 通过 FileStream 功能为您提供了两全其美的优势 - 可能值得一试。 http://technet.microsoft.com/en-us/library/bb933993.aspx

    【讨论】:

      【解决方案5】:

      将图像存储到数据库的优点之一是它可以跨系统移植并且独立于文件系统布局。

      【讨论】:

        【解决方案6】:

        最简单/最高效/最可扩展的解决方案是将图像存储在文件系统上。如果需要考虑安全性,请将它们放在 Web 服务器无法访问的位置,并编写一个脚本来处理安全性并提供文件。

        假设您的网络/应用服务器和数据库服务器是不同的机器,您将图像放入数据库会受到以下影响:(1) 两台机器之间的网络延迟,(2) 数据库连接开销,(3) 消耗为每个提供的图像附加一个数据库连接。我更关心最后一点:如果您的网站提供大量图片,您的 Web 服务器将消耗大量数据库连接,并可能耗尽您的连接池。

        【讨论】:

        • 当然不是最具扩展性的解决方案。
        【解决方案7】:

        如果您的应用程序在多台服务器上运行,我会将您的图像的参考副本存储在数据库中,然后根据需要将它们缓存在文件系统上。与尝试横向同步文件系统相比,这样做更不容易出错。

        如果您的应用程序位于单个服务器上,那么是的,请坚持使用文件系统并让数据库维护数据路径。

        【讨论】:

          【解决方案8】:

          当然,大多数 SQL 数据库在设计时都没有考虑到提供图像,但是将它们放入数据库中会带来一定的便利。

          例如,如果您已经运行了一个数据库并配置了复制。您立即拥有一个 HA 映像存储,而不是尝试进行一些基于 rsync 或 nfs 的文件系统复制。此外,拥有一堆 Web 进程(或设计一些新服务)来将文件写入磁盘会稍微增加您的复杂性。实际上,它只是更多的活动部件。

          至少,我建议将有关图像的“元”数据(例如任何权限、谁拥有它等)和实际数据分开到不同的表中,这样就可以很容易地切换到不同的表数据存储下线。再加上某种 CDN 或缓存应该可以为您提供相当不错的性能,所以我认为这取决于该应用程序需要具备多大的可扩展性以及您如何在易于实施之间取得平衡。

          【讨论】:

            【解决方案9】:

            您不必存储 URL(如果您觉得这不安全)。您可以只存储一个在别处引用该图像的唯一 ID。

            数据库存储往往比文件系统更昂贵且维护成本更高 - 因此我不会在数据库中存储大量图像。

            【讨论】:

              【解决方案10】:
              • 数据数据库
              • 文件的文件系统

              【讨论】:

              • 以及对一切的概括!
              • 图片在哪些方面不是数据?
              • @AdamRobinson 已经 7 年没有看到这个评论了。正忙于备份在数据库中存储图像的 web 应用程序的数据库:)
              【解决方案11】:

              当您在数据库中存储 TB 的图像数据时,灾难恢复绝对没有乐趣。您最好找到一种更好的方法来分发数据以使其更可靠等...当然所有开销(上面提到的)在复制等时都会成倍增加...

              别这样!

              【讨论】:

                【解决方案12】:

                这看起来真的像一个 KISS(保持简单愚蠢)问题。文件系统是为了方便处理图片文件的存储而设计的,但在数据库中做起来并不容易,而且容易弄乱数据。当您只需要担心文件安全性时,为什么还要在 sql 和渲染中遇到性能损失和所有困难?您还可以使用 NFS 或 CIFS 处理混合系统。文件系统是成熟的技术。更简单、更健壮。

                【讨论】:

                  【解决方案13】:

                  我将图像存储在数据库中以用于演示应用程序。我这样做的原因是安全 - 删除我不应该删除的记录不是什么大问题,但删除我不应该删除的文件可能是个问题!

                  如果性能成为问题,我会调查是否真的有可能删除恶意文件。

                  【讨论】:

                    【解决方案14】:

                    如果是定期从数据库中提取的图像,我总是会尝试使用文件系统。

                    如果是偶尔需要拉出来的图片,把它们保存在数据库中让生活更轻松,我完全没有问题。

                    【讨论】:

                      猜你喜欢
                      • 2010-11-07
                      • 2011-05-31
                      • 2011-04-04
                      • 2018-07-22
                      • 1970-01-01
                      • 2013-11-01
                      • 2018-05-17
                      • 2015-02-05
                      • 2013-01-12
                      相关资源
                      最近更新 更多