【问题标题】:What is better for performance - many files in one directory, or many subdirectories each with one file?什么对性能更好 - 一个目录中有许多文件,或者每个子目录都有一个文件?
【发布时间】:2013-07-23 17:28:24
【问题描述】:

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

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

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

其中 ID 是 users 的唯一 ID 号

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

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

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

【问题讨论】:

  • 这取决于文件系统。
  • 对于不经常更改的小型只读文件(如头像图片),使用专用数据库可能有意义。即使是本地 SQLite3 实例也值得。请参阅sqlite.org/intern-v-extern-blob.html - 但在 Web 服务器上下文中,静态文件资源更有意义。

标签: file filesystems


【解决方案1】:

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

参考:article

【讨论】:

  • 有多少个文件?如果没有这些信息,我认为这不是结论性的。
  • 文章指出1000万个文件。
  • 参考文章编辑修改结论:“结论2:坚持自定义智慧,使用深度目录文件系统。但要警惕目录层级过多的性能代价。”
【解决方案2】:

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

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

【讨论】:

  • 在存储非平凡(和可变)大小的二进制 blob 时,并非所有数据库都表现良好。不会直接推荐这个,除非没有基准测试。
  • @FrankH。你说的对。我想这也取决于应用程序的上下文。
【解决方案3】:

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

How many files in a directory is too many (on Windows and Linux)?

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

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

【讨论】:

  • 我读过那个,但我不知道这个限制也适用于子目录。是的,我问的是基本文件系统(windows/ntfs 或 linux/ext3)。
  • 我还可以根据超级计算的经验补充说,即使您的文件系统将支持目录中的一百万个文件(有些会),即使是基本操作,您的性能也会急剧下降.许多在 dir 的大小上是线性的。像 ls 这样的东西每个条目都需要一些系统调用(获取文件名、统计文件、检查安全 xattrs)……乘以一百万,你就会遇到严重的瓶颈。可能需要几个小时才能返回。
  • 因此,使用数字 ID,如果我使用您建议的解决方案并将文件保存在其中,例如。 /12/34/56/my_file.jpg(对于 ID 中的每 2 位数字,一个新的子目录)这会将每个目录中的子目录数量限制为最多 100 个(0-99)......这足以获得不错的性能?
  • 那行得通...我会选择一个稍微宽一些的分支因子,比如 123/456/ 每个目录有一千个文件。这意味着最大深度在 2 到 3 之间(日志基数为 1K 的 10M),同时对于文件系统仍然非常易于管理,并且仍然相当人类可读,应该,上帝保佑,您需要实际查看内容。
【解决方案4】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    相关资源
    最近更新 更多