成千上万的文件在同一个Linux目录中是否正确(性能明智)?

众所周知,在Windows中,当您尝试打开其中一个文件时,具有太多文件的目录将具有可怕的性能。 我有一个只能在Linux下执行的程序(目前它在Debian-Lenny上,但我不想具体说明这个发行版),并将许多文件写入同一个目录(作为一个存储库)。 我认为“很多”是每天几十,这意味着一年之后,我想有5000-10000个文件。 它们是为了保存(一旦文件被创build,它从来没有被删除),并假定硬盘具有所需的容量(如果没有,应该升级)。 这些文件的大小范围很广,从几KB到几十MB(但是不超过)。 名称始终是数值,逐渐生成。 我担心长期的性能下降,所以我会问:

  • 把全部写到同一个目录是可以的吗? 或者我应该考虑为每个X文件创build一组子目录?
  • 我是否需要一个特定的文件系统用于这样的目录?
  • 什么是更强大的select? 专门的文件系统? 哪一个?
  • 任何其他考虑/推荐?

Solutions Collecting From Web of "成千上万的文件在同一个Linux目录中是否正确(性能明智)?"

这很大程度上取决于文件系统。

ext2和ext3每个目录有32,000个文件的硬性限制。 这比你所问的要多一点,但足够接近,我不会冒险。 而且,ext2和ext3会在每次通过目录中的名称访问文件时执行线性扫描。

ext4据说解决了这些问题,但是我不能亲自担保。

XFS是从一开始就为这种事情设计的,即使把数以百万计的文件放在目录中也能正常工作。

所以如果你真的需要大量的文件,我会使用XFS或者ext4。

请注意,如果文件数量巨大(除非使用“ls -f”),否则没有文件系统会使“ls”快速运行,因为“ls”将读取整个目录并对其进行排序。 成千上万的可能不是什么大不了的事,但一个好的设计应该乍一看超出你想要的范围。

对于您描述的应用程序,我可能会创建一个层次结构,因为对于查看它的人来说,几乎没有任何额外的编码或精力。 具体而言,您可以将您的第一个文件命名为“00/00/01”而不是“000001”。

如果你使用没有目录索引的文件系统,那么在一个目录中有大量的文件是非常糟糕的(例如,> 5000)。

但是,如果你有目录索引(在ext3中更新的发行版默认启用),那么这不是一个问题。

然而,它确实打破了很多工具,在一个目录下有很多文件(例如,“ls”将stat()所有的文件,这需要很长时间)。 你可能很容易分裂成子目录。

但不要过头。 不要不必要地使用多层嵌套子目录,这只是使用大量inode,并使元数据操作变慢。

我见过更多“嵌套目录级别太多”的例子,比我看到的“每个目录文件太多”的情况还要多。

我为您提供的最佳解决方案(而不是从微文件系统基准测试中引用一些值)是自己测试一下。

只要使用您选择的文件系统。 为100个,1000个和10000个条目创建一些随机测试数据。 然后,测量系统执行您关心的操作所需的时间(打开文件,读取100个随机文件等)。

然后,比较时间并使用最佳解决方案(将它们全部放在一个目录中;将每年放入一个新目录;将每年的每个月份放到一个新目录中)。

我不清楚你正在使用什么,但创建一个目录是一次(也可能很容易)的操作,所以为什么不这样做,而不是改变文件系统或尝试一些其他更耗时的东西?

除了其他答案之外,如果巨大的目录由已知的应用程序或库管理,则可以考虑用其他方式替换它,例如:

  • 一个GDBM索引文件; GDBM是一个非常普通的库,它提供了索引文件,它将任意键(一个字节序列)与一个任意值(另一个字节序列)关联起来。
  • 也许是像MySQL或PostGresQL数据库内的一个表。 请注意索引。
  • 一些其他的方式来索引数据

上述方法的优点包括:

  1. 空间性能的大量收集的小项目(每个小于千字节)。 文件系统需要每个项目的inode。 索引系统可能具有更小的粒度
  2. 时间表现:你不能访问每个项目的文件系统
  3. 可伸缩性:索引方法可以满足大量需求:GDBM索引文件或数据库可以处理数百万个项目。 我不确定你的目录方法会轻松扩展。

这种方法的缺点是不能显示为文件。 但正如MarkR的回答提醒你的那样, ls在巨大的目录上表现得相当糟糕。

如果你坚持文件系统的方法,许多软件使用大量的文件正在组织他们的子目录,如aa/ ab/ ac/ay/ az/ ba/bz/

在一个目录中有大量的文件是不利于性能的。 检查文件的存在通常需要对目录进行O(n)扫描。 创建一个新文件将需要进行相同的扫描,并锁定该目录以防止在创建新文件之前更改目录状态。 一些文件系统可能会比较聪明(使用B树或其他),但是实现对文件系统长处和短处的关系越少,对于长期维护越好。 假设有一天可能决定在网络文件系统(存储设备甚至云存储)上运行应用程序。 巨大的目录在使用网络存储时是一个糟糕的主意。

  • 把全部写到同一个目录是可以的吗? 或者我应该考虑为每个X文件创建一组子目录?

根据我的经验,如果你做了诸如用ls获取列表之类的东西,那么只有使用许多文件才能减慢目录的速度。 但是这主要是ls的错误,使用echo和find等工具可以更快速地列出目录的内容(见下文)。

  • 我是否需要一个特定的文件系统用于这样的目录?

关于一个目录中的文件数量,我不这么认为。 我确定一些文件系统在一个目录中的许多小文件上表现更好,而另外一些则在大文件上做得更好。 这也是个人品味的问题,类似于vi和emacs。 我更喜欢使用XFS文件系统,这是我的建议。 🙂

  • 什么是更强大的选择? 专门的文件系统? 哪一个?

XFS绝对健壮和快速,我在很多地方使用它,作为启动分区,oracle表空间,源代码控制空间,你的名字。 它在删除性能方面缺乏一点,但是否则这是一个安全的选择。 另外它支持在安装时增加尺寸(实际上这是一个要求)。 那就是你只要删除分区,在相同的起始块重新创建它,以及任何大于原始分区的结束块,然后在挂载的文件系统上运行xfs_growfs。

  • 任何其他考虑/推荐?

往上看。 另外在一个目录中有5000到10000个文件应该不成问题。 实际上,就我所知,除了诸如“ls”和“rm”之类的实用程序之外,它不会任意地减慢文件系统的速度。 但是你可以这样做:

 find * | xargs echo find * | xargs rm 

带有文件的目录树(例如以“a”开头的文件名称的目录“a”)给出的目录树就是外观的好处,它看起来更有组织性。 但是,你没有一个概述…所以你想要做的应该没问题。 🙂

我忽略了说你可以考虑使用一些名为“稀疏文件” http://en.wikipedia.org/wiki/Sparse_file