当我需要进行某些通配符匹配时,我遇到了单个目录中数十万个文件的性能问题。从我的应用程序的角度来看,一个简单的解决方案是将文件放置在深度嵌套的文件夹中。
整个层次结构中文件夹总数的预期上限为 9^30。可以假设永远不会达到此限制(请参阅下面的评论)。随着文件的添加,文件夹的数量只会增加。
问题:当在 ext4 文件系统上创建大量文件夹时,从文件系统的角度来看是否有任何影响?例如消耗了多少空间。一个只包含另一个文件夹的文件夹?我会因为元数据太多而遇到麻烦吗?
(从我的应用程序的角度来看,与更简单的层次结构中基于哈希的文件夹相比,上述结构有一定的优势,我知道组织数据的“更好”方法)
答案1
每个文件夹占用一个 inode(256 字节)和至少一个块(可能是 4096 字节)。更大的问题可能是多个层次结构层的访问时间。
性能问题可能不是由文件夹大小引起的,而是由路径名扩展引起的。路径名扩展有两个问题:
- 它对结果进行排序(无法禁用),对于大量项目来说,这需要花费令人不安的长时间。
- 它创建(取决于使用类型)非法命令行(太多项目)。
您应该在应用程序级别解决这个问题。一次读取 100 个文件名(未排序,使用find
或ls -U
),并在必要时对这些小组进行排序。这还允许并行读取磁盘和 CPU 使用情况。
如果您确实需要路径名扩展和/或排序,那么您可以通过按排序顺序将文件添加到其(空)目录中来大大加快该过程(如果文件很少更改)。
答案2
Ext4 在处理大型目录时比以前的版本稍好一些,但在同一目录中包含 10,000 个左右的文件后仍然会陷入困境。将目录层次结构中的文件分离出几层深度是维持性能的常见解决方案。查找文件时,每个深度增量都需要额外的间接寻址,但宽度随深度呈指数增加。
例如,如果您的文件名称仅由字母、数字和一些标点符号组成,则不要将它们全部放在同一目录中,而是根据文件名的前两个字符创建子目录。也就是说,该文件foobar
存储在fo/foobar
.如果子目录中的文件仍然过多,请增加深度:fo/ob/foobar
,依此类推。您必须进行基准测试来确定要分割多少个字符以及在什么深度停止。
有很多潜在的目录,但大多数最终都会是空的。因此,不要在开始时创建所有目录,而是按需创建它们。例如,如果您需要创建文件foobar
,则创建目录(fo
如果该目录尚不存在),然后对 执行相同操作fo/ba
,然后存储foobar
在 中fo/ba/foobar
。
除非文件很小(小于 4kB),否则目录所占的空间量可以忽略不计。即使文件很小,只要深度不过分,目录也会比文件少得多。但是,如果您有大量小文件,则表明您应该使用数据库。