NTFS目录有10万个条目。如果分散到100个子目录中,性能会提高多少?

6
背景 我们有一个自己开发的基于文件系统的缓存库。由于条目数量很大(例如高达100,000个),我们当前在一个安装中存在性能问题。问题是:我们将所有fs条目存储在一个“缓存目录”中。非常大的目录性能不佳。
我们正在考虑将这些条目分散到子目录中,就像git一样,例如100个子目录,每个子目录约1,000个条目。 问题 我知道较小的目录尺寸会有助于文件系统访问。但是,“分散到子目录中”是否会加快遍历所有条目的速度,例如枚举/读取所有100,000个条目?也就是说,当我们从FS存储初始化/预热缓存时,我们需要遍历所有100,000个条目(并删除旧条目),这可能需要10多分钟。
“分散数据”是否会减少此“遍历时间”?此外,此“遍历”实际上可以/会删除过期条目(例如早于N天的条目)。“分散数据”是否会改善删除时间? 其他背景 -NTFS -Windows家庭操作系统(Server 2003、2008) -Java J2EE应用程序。
我/我们将感激任何有关文件系统可扩展性问题的建议。
提前感谢。
威尔

2
你尝试过调整文件系统吗?例如,禁用短文件名? - barti_ddu
4个回答

10

我曾认为将文件分散到子目录中会加快操作速度。

于是我进行了一些测试:我生成了从AAAA到ZZZZ(26^4个文件,大约为450K)的文件,并将它们放置在一个NTFS目录中。我还将相同的文件放置到从AA到ZZ的子目录中(即按其名称的前两个字母将文件分组)。然后我做了一些测试 - 枚举和随机访问。我在创建和测试之间重新启动了系统。

与子目录相比,扁平结构表现出稍微更好的性能。我认为这是因为目录被缓存,并且NTFS索引目录内容,所以查找很快。

需要注意的是,完整的枚举(在两种情况下)对于40万个文件需要大约3分钟。虽然这个时间相当长,但子目录会使情况变得更糟。

结论:在特定的NTFS上,如果可以访问这些文件中的任何一个,则没有必要将文件分成子目录。如果您有缓存,我也建议测试按日期或域分组的文件,假设某些文件比其他文件更频繁地被访问,并且操作系统不需要将所有目录保存在内存中。但是,对于您的文件数量(少于100K),这可能不会带来显著的好处。我认为您需要自己测量这些特定的情况。

更新:我将我的随机访问测试缩小到仅访问一半的文件(从AA到OO)。假设这将涉及一个平面目录和只有一半子目录(给予子目录情况的奖励)。但扁平目录表现更好。因此,我认为,除非有数百万个文件,否则在NTFS上将它们保持在一个扁平目录中将比将其分组到子目录中快。


4
如果您从未需要对缓存目录进行统计或列出,并且仅通过完整路径打开和访问其中的文件,则在目录中有多少文件并不重要(至少在100k个文件级别上)。
在这种情况下,许多缓存框架和以文件系统为基础的存储引擎将根据文件名中的第一个字符创建子目录。例如,如果您将文件“abcdefgh.png”存储在缓存中,则应将其放入“cache/a/b/cdefgh.png”而不是“cache/abcdefgh.png”。这假定您的文件名的前两个字母的分布在字符空间中大致均匀。
正如您所提到的,由于您主要的任务涉及列出或遍历目录是删除过时的文件,因此我建议您创建基于文件被缓存的日期和/或时间的目录,即“cache/2010/12/04/22/abcdefgh.png”,并且无论在哪里索引缓存,都要确保按文件名和日期(特别是如果它在数据库中)进行索引,以便您可以快速从索引中按日期删除项目并删除相应的目录。

0
你是如何加载缓存的?如果你使用标准的Java文件系统交互,那么这将是你的第一个瓶颈 - Java在文件夹内容迭代方面表现得相当糟糕 - 如果你在迭代时对每个文件进行检查(获取修改日期,确保文件不是目录等),性能可能会受到很大影响(所有这些都涉及到与本地的往返)。转向基于本机FindFirstFile的解决方案可能会提供显着的(数量级)改进。FindFirstFile在每个迭代步骤中返回有关文件的所有信息。Java File.listFiles()返回路径列表。然后,当您查询属性或其他元数据时,每个调用都是对文件系统的往返。非常低效。
好了 - 这就过去了。接下来,在NTFS中对巨大目录的原始迭代并不比n叉树方法(文件夹和子文件夹等)慢。对于FAT32来说,这是一个非常重要的问题 - 但是NTFS处理这种事情相当出色。话虽如此,拆分成子文件夹可以开启一些自然的并行化机会,这在单个文件夹中要实现得多困难。如果您可以生成10或15个线程,每个线程都访问不同的文件夹,那么您可以有效地消除磁盘延迟作为一个贡献因素。
我建议你从性能分析开始(当然,你已经知道了)- 看看负载时间的主要来源在哪里。你可能会感到惊讶(例如,在我们的一个应用程序中,它处理了很多文件列表,当检查isDirectory()时,我惊讶地发现我们被击中了多长时间 - 像在目录/文件确定之前进行日期比较这样的简单更改使我们的迭代速度提高了30%)。

0
有一件值得关注的事情是您的磁盘子系统如何排列。虽然磁盘的容量迅速增长,但它们的访问时间并没有变得更快。使用不同的磁盘排列(使用更多的磁盘)或使用固态硬盘驱动器可能是一个选择。例如,固态硬盘没有移动部件,可以在10秒内处理100K个文件,使预热变得不必要。

“NTFS”而不是“NFS”。该文件系统是本地的,而不是远程的。 - user331465
@user331465,非常好的观点。在这种情况下,我建议您查看您的硬件。您只能以驱动器可以移动的速度进行操作。 - Peter Lawrey

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