我应该把照片存储在哪里?文件系统还是数据库?

11
可能是重复问题:
存储上传的照片和文档 - 文件系统 vs 数据库 blob

我开始开发一个 Web 应用程序,其主要目的是显示照片。用户也可以上传照片。

首先需要解决的问题是在哪里存储这些照片:文件系统还是数据库。

我将使用 Windows 主机托管该站点。数据库是 MySQL,后端代码使用 ASP.NET MVC 实现的 C#。


12
让圣战开始吧... - Muad'Dib
@Locksfree 可能有数千张图片。根据人们是否实际使用该网站,可能会更多。 - AngryHacker
10个回答

31

当然是使用文件系统,除非你想写一篇类似于thedailywtf的故事。最简单的方法是根据文件本身可以派生出的属性(例如其SHA-1哈希)来组织照片,然后将哈希存储在数据库中,与照片的主键和其他属性(上传者、上传日期等)相关联。

此外,将照片分散到文件系统中也是一个好主意,这样你不会在单个目录中拥有数百万个文件。因此,你将会有类似于这样的结构:

storage/00/e4/f56c0de1c61fdb926e79e8a0a65bd12930c9.jpg
storage/25/9a/ec1c55bfb660548a6770238668c4b117d92f.jpg
storage/5d/d5/4b01d98f17a9ad9dd1526b49ba39b5aa37a1.jpg
storage/63/49/6f740b6c284ce6685dc17d473a7360ace249.jpg
storage/b1/75/066d178188dde110149a8422ab651b0ee615.jpg
storage/b1/20/a2b7d02b7b0c43530677ab06235382a37e20.jpg
storage/da/39/a3ee5e6b4b0d3255bfef95601890afd80709.jpg

如果你将来需要迁移到分片存储,这也很容易移植。


1
SHA-1哈希用于创建目录和文件名的想法非常明智。答案被接受。 - AngryHacker
2
但是删除呢?例如:两个用户上传了相同的文件。因为哈希(路径)相同,所以只会存在一个文件。当其中一个用户删除照片时,第二个用户也将失去它。我说得对吗? - binball
@John Millikin,你是如何在数据库中生成和存储存储目录的? - Code Junkie
1
@binball 你可以为每个哈希值保留一个简单的计数器。如果用户上传的文件与现有哈希值匹配,只需将计数器加一。如果用户删除文件,则减少计数器,如果计数器达到零,则安全删除文件。这是一种“引用计数”的形式。 - Bert
我有一个类似的问题,关于工业界开发人员如何组织文件夹和上传文件。我看到了这个stackoverflow的帖子,其中有一个很好的答案,但它已经存在了11年,所以在2021年,按照这种方式组织上传的文件仍然被认为是最佳实践吗?谢谢。 - Ham
1
@Han 是的,我在过去的11年中多次将文件存储在文件系统中。效果还不错。但是,对于较小的安装,我也将照片保存在数据库中,没有性能下降。这很方便,因为您可以在其他地方备份和恢复数据库,一切都在那里 - 您不必单独复制照片。但是,它会使数据库膨胀很多。因此,您必须权衡您的情况的利弊。 - AngryHacker

4
如果您正在围绕照片建立网站,则可以忘记数据库。如果它变得受欢迎,您的数据库将受到重击,并且其大部分时间将用于传递照片。此外,数据库不太容易扩展。在文件系统中保留这些内容有很多优势。您可以进行良好的扩展,使用静态内容服务器,使用内容交付服务。
此外,Amazon S3或其他云提供商确实具有其优点。例如,S3 + Amazon CloudFront将提供良好的性能。CloudFront会在全球各地的服务器上缓存您的文件,因此它们将非常易于/快速地从任何地方访问。但是,如果我们谈论图片并且该网站变得流行,您的账单可能会相当高。
对于S3,Amazon按存储和进出云的传输收费。 CloudFront每次传输都会收费

4
如果您正在使用SQL Server 2008,则有一个名为Filestream的数据类型,可以处理关于数据库变得更大的大部分问题。它处理了在文件系统和表格之间同步的所有烦人细节。
请查看此处有关该主题的博客文章:在SQL Server 2008(Katmai)中存储任何数据

顺便说一下,这篇文章只是提供信息而已... :) - Siewers

3

通常情况下,人们将像图片这样的二进制数据存储在文件系统中,而不是数据库中。他们通过文件系统路径引用数据库中的数据。从数据库检索二进制大对象(BLOBs)比允许Web服务器从文件系统提供静态文件速度更慢。


3

我会使用类似亚马逊S3的服务。

但是,如果选择在文件系统和数据库之间,我会选择文件系统,因为从文件系统提供图片比从数据库提供更快。


3

只有当我拥有一组服务器并且正在使用数据库复制将照片自动复制到群集中的每台机器时,我才会将照片作为BLOBs存储在数据库中。

如果您只是将照片存储为文件,并在数据库中存储照片的文件名,则生活会更加简单。如果您需要为照片创建唯一的文件名,可以使用数据库的主键整数作为文件名的一部分。但是,您也可以像John Milliken建议的那样,仅使用照片本身的哈希值。这很简单,而且简单通常更好。


可以在文件系统上完成。无需将图像放入数据库中。 - Jim Blizard
1
“can also be done”? 这个说法有点简洁。您是在说可以自动复制吗?我想是的;肯定有人已经编写了文件复制系统。但是,如果您已经设置了数据库复制,那么将照片放入其中可能会更简单,而不是配置和调试两个单独的复制系统。您是否不同意? - steveha

3

有些人指出,如果所有的东西都在数据库中,包括备份和保留引用完整性,那么管理起来会更容易。


在我看来,甚至考虑将它们存储在数据库中的唯一原因。 - peterchen
我会说那是一个非常好的理由。 - ChaosPandion

3
如果您将图片存储在数据库中,数据库会迅速增长并变得非常大。从数据库中获取图像以进行显示比从文件系统中获取要稍微复杂一些。另一方面,您需要确保文件名和路径与存储在数据库中的内容不会不同步。过去,我选择将其存储在磁盘上而不是数据库中。这使我更容易将数据库移动到不同的服务器。效果很好。

2

当你拥有一个Blob数据库时,生活变得非常容易。你应该忘记文件系统管理所带来的噩梦。

编辑

ID
VARBINARY

从经验来看,这是一种有效管理二进制文件的方法。你只需要一个只包含二进制文件的数据库。这样备份会更加困难吗?


2
直到你需要备份数据库,然后,惊喜,它混杂着数千吉字节的二进制垃圾和元数据。 - John Millikin
1
是的,这应该是任何软件架构的主要目标……让开发者的生活变得“非常轻松”。不要管那些必须处理几百万兆字节数据库的运维人员,也不要理会那些不得不等待图片从原本只用于存储数据的服务器中加载出来的用户。 - Jim Blizard
如果你更关心易于开发或学术考虑,而不是可扩展性和可维护性的实际问题和一些IT方面的问题。 - Jim Dennis
1
请告诉我如何使用文件系统更高效或可扩展? - ChaosPandion
1
文件系统就是一个数据库——它从一开始就被设计用来存储文件/文档,而不是像关系型数据库那样用于存储小的、重复的字段。你可以使用关系型数据库管理文件,但当文件在文件系统中时,你会发现有更多自然和直观的工具来处理它们。 - steamer25
显示剩余2条评论

2
我们在一个项目中也面临了类似的决策。将图片和其他大型对象存储到数据库中的优点是,这样做可以减少意外或故意删除/更改数据的风险。但我们没有选择这种方式,而是将路径信息存储在数据库中,并通过UNC路径引用数据。数据路径分为两部分 - 一部分是相对于所在机器的位置引用数据的位置,另一部分是指向该组数据所在的机器。当需要移动数据时,我们可以更新相应的路径信息。
从数据库中获取数据速度确实很快,这是最终的决定因素之一。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接