15

在构建 Web 应用程序时,我们经常有与数据库条目相关联的文件,例如:我们有一个user表,每个类别都有一个avatar字段,其中包含相关图像的路径。

为了确保文件名没有冲突,我们可以:

  • 上传文件时重命名为ID.jpg;那么路径将是/user-avatars/ID.jpg
  • 或者为每个实体创建一个子目录,保持原文件名不变;那么路径将是/user-avatars/ID/original_filename.jpg

其中 ID 是users的唯一 ID 号

从应用程序逻辑的角度来看,两者都完全有效。

但是从文件系统性能的角度来看,哪一个会更好?我们必须记住,category条目的数量可能非常高(数百万)。

一个目录可以容纳的子目录数量是否有限制?

4

4 回答 4

10

这将取决于您的文件系统,但我假设您正在谈论一些简单的东西,例如 ext3,并且您没有运行分布式文件系统(其中一些非常擅长于此)。通常,文件系统在单个目录中的一定数量的条目上表现不佳,无论这些条目是目录还是文件。因此,无论是为每个图像创建一个目录还是在根目录中创建一个图像,都会遇到缩放问题。如果你看这个答案:

一个目录中有多少文件太多(在 Windows 和 Linux 上)?

您会看到 ext3 在一个目录中的条目数量约为 32K 时遇到了限制,远低于您的建议。

在我的脑海中,我建议对多级目录树进行一些基本的分片,例如 /user-avatars/1/2/12345/original_filename.jpg。(或者适合您的 ID 类型的东西,但我将您的问题解释为关于数字 ID。)当您决定要在存储集群中分发时,这样做也将使您的生活更轻松,因为您可以传播目录大约。

于 2013-07-24T12:28:06.810 回答
3

任何文件系统都很难处理一个父目录中的数百万个条目(文件或目录)。虽然现代文件系统使用排序和各种树算法来快速搜索所需文件,但即使使用 Windows Explorer 或 Midnight Commander 或任何其他文件管理器导航到文件夹也会很复杂,因为文件管理器必须读取目录的内容。这同样适用于文件搜索。因此,子目录是首选。

然而我需要注意的是,当所有文件都在一个目录中时,访问特定文件会比至少在 NTFS 上将它们分成子目录时要快一些(我自己用 400K 文件测量了几次)。

于 2013-07-24T11:05:10.363 回答
2

我一直有一个非常相似的问题,即 html 文件而不是图像。试图将数百万个它们存储在 ext4 的 Ubuntu 服务器中。结束运行我自己的基准测试。发现平面目录的性能更好,同时使用起来更简单:

基准

参考:文章

于 2018-12-22T03:52:39.017 回答
1

如果你真的想使用文件,也许你最好的办法是将文件分成几个子目录,这样你就不会遇到限制。例如,如果你有一个 ID 123456,你可以把它放在 /12/34/56.jpg 中。

但是,我建议您只使用数据库来存储这些数据,因为您已经在使用一个。您可以将图像数据和 ID 存储在同一个表中,并且您不必担心处理文件的一些烦人事务,例如确保权限设置正确等。

于 2013-07-24T12:45:07.433 回答