29

我正在开发的产品每天收集数千个读数,并将它们作为 64k 二进制文件存储在 NTFS 分区 (Windows XP) 上。经过一年的生产,单个目录中有超过 300000 个文件,并且数量还在不断增长。这使得从 Windows 资源管理器访问父/祖先目录非常耗时。

我试过关闭索引服务,但没有任何区别。我还考虑将文件内容移动到数据库/zip 文件/tarball 中,但单独访问这些文件对我们是有益的;基本上,这些文件仍然需要用于研究目的,研究人员不愿意处理其他任何事情。

有没有办法优化 NTFS 或 Windows 以便它可以处理所有这些小文件?

4

14 回答 14

35

只要您告诉 NTFS 停止创建与 16 位 Windows 平台兼容的替代文件名,NTFS 实际上可以很好地处理目录中超过 10,000 个文件。默认情况下,NTFS 会自动为每个创建的文件创建一个“8 点 3”文件名。当目录中有许多文件时,这会成为一个问题,因为 Windows 会查看目录中的文件以确保它们创建的名称尚未被使用。您可以通过将 NtfsDisable8dot3NameCreation 注册表值设置为 1 来禁用“8 点 3”命名。该值位于 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\FileSystem 注册表路径中。进行此更改是安全的,因为只有为非常旧的 Windows 版本编写的程序才需要“8 点 3”名称文件。

此设置需要重新启动才能生效。

于 2008-10-24T18:14:43.043 回答
28

目录中有 10,000 个文件后,NTFS 性能会严重下降。您所做的是在目录层次结构中创建一个附加级别,每个子目录有 10,000 个文件。

值得一提的是,这是 SVN 人员在1.5 版本中采用的方法。他们使用 1,000 个文件作为默认阈值。

于 2008-09-22T16:29:51.987 回答
9

性能问题是由单个目录中的大量文件引起的:一旦消除它,就应该没问题。这不是特定于 NTFS 的问题:事实上,在大型 UNIX 系统上的用户主目录/邮件文件中经常会遇到这种问题。

解决此问题的一种明显方法是将文件移动到名称基于文件名的文件夹中。假设您所有的文件都有类似长度的文件名,例如 ABCDEFGHI.db、ABCEFGHIJ.db 等,请创建如下目录结构:

ABC\
    DEF\
        ABCDEFGHI.db
    EFG\
        ABCEFGHIJ.db

使用这种结构,您可以根据文件名快速定位文件。如果文件名具有可变长度,请选择最大长度,并在前面加上零(或任何其他字符)以确定文件所属的目录。

于 2008-09-22T16:33:15.317 回答
5

在过去,我已经看到了巨大的改进,例如通过文件名的第一个然后第二个字母将文件拆分为嵌套的目录层次结构;那么每个目录不包含过多的文件。然而,操作整个数据库仍然很慢。

于 2008-09-22T16:27:55.517 回答
4

如果您可以计算文件的名称,则可以按日期将它们分类到文件夹中,以便每个文件夹仅包含特定日期的文件。您可能还想创建月份和年份层次结构。

此外,您能否将超过一年的文件移动到不同(但仍可访问)的位置?

最后,再一次,这要求您能够计算名称,您会发现直接访问文件比尝试通过资源管理器打开文件要快得多。例如,从命令行说
notepad.exe "P:\ath\to\your\filen.ame"
实际上应该很快,假设您知道所需文件的路径而无需获取目录列表。

于 2008-09-22T16:27:36.467 回答
4

您可以尝试使用 Solid File System 之类的东西。

这为您提供了一个虚拟文件系统,应用程序可以像挂载物理磁盘一样挂载该文件系统。您的应用程序会看到很多小文件,但硬盘上只有一个文件。

http://www.eldos.com/solfsdrv/

于 2008-09-22T16:31:47.270 回答
4

我过去多次遇到这个问题。我们尝试按日期存储,将文件压缩到日期以下,这样您就不会有很多小文件等。所有这些都是针对将数据作为大量小文件存储在 NTFS 上的真正问题的创可贴。

您可以转到 ZFS 或其他可以更好地处理小文件的文件系统,但仍然要停下来询问您是否需要存储小文件。

在我们的例子中,我们最终进入了一个系统,即某个日期的所有小文件都以 TAR 类型的方式附加,并带有简单的分隔符来解析它们。磁盘文件从 120 万个减少到几千个。它们实际上加载得更快,因为 NTFS 不能很好地处理小文件,而且驱动器能够更好地缓存 1MB 文件。在我们的案例中,与存储文件的实际存储和维护相比,找到文件正确部分的访问和解析时间最少。

于 2008-09-22T16:44:23.387 回答
3

一个常见的技巧是简单地创建一些子目录并将文件分开。

例如,Doxygen 是一个可以生成大量 html 页面的自动化代码文档程序,它可以选择创建两级深度目录层次结构。然后这些文件均匀分布在底部目录中。

于 2008-09-22T16:29:06.450 回答
3

在一个目录中拥有数十万个文件确实会削弱 NTFS,而您对此无能为力。您应该重新考虑以更实用的格式存储数据,例如一个大的压缩包或数据库。

如果你真的需要为每个读数单独的文件,你应该将它们分类到几个子目录中,而不是将它们都放在同一个目录中。您可以通过创建目录层次结构并根据文件名将文件放在不同的目录中来做到这一点。这样,您仍然可以只知道文件名来存储和加载文件。

我们使用的方法是取文件名的最后几个字母,将它们反转,并从中创建一个字母的目录。例如,考虑以下文件:

1.xml
24.xml
12331.xml
2304252.xml

您可以将它们分类到目录中,如下所示:

data/1.xml
data/24.xml
data/1/3/3/12331.xml
data/2/5/2/4/0/2304252.xml

此方案将确保您在每个目录中的文件永远不会超过 100 个。

于 2008-09-22T16:41:30.583 回答
2

除了将文件放在子目录中..

就个人而言,我会开发一个应用程序来保持该文件夹的界面相同,即所有文件都显示为单独的文件。然后在应用程序后台实际获取这些文件并将它们组合成一个更大的文件(并且由于大小始终为 64k,因此获取所需的数据应该相对容易)以摆脱您所拥有的混乱。

因此,您仍然可以让他们轻松访问他们想要的文件,还可以让您更好地控制所有内容的结构。

于 2008-09-22T16:30:49.877 回答
1

考虑将它们推送到另一台服务器,该服务器使用对大量小文件更友好的文件系统(例如 Solaris w/ZFS)?

于 2008-09-22T16:27:40.133 回答
1

如果数据有任何有意义的、分类的方面,您可以将它们嵌套在目录树中。我相信减速是由于一个目录中的文件数量,而不是文件本身的数量。

最明显的一般分组是按日期,并为您提供三层嵌套结构(年、月、日),每个叶目录中的文件数量(1-3k)具有相对安全的界限。

即使您能够提高文件系统/文件浏览器的性能,听起来这也是您将在 2 年或 3 年内遇到的问题......只需查看 0.3-1 百万个文件的列表就会产生成本,因此从长远来看,找到仅查看较小文件子集的方法可能会更好。

使用“find”之类的工具(在 cygwin 或 mingw 下)可以使浏览文件时不存在子目录树的问题。

于 2008-09-22T16:31:50.873 回答
1

每天使用时间戳重命名文件夹。

如果应用程序将文件保存到 c:\Readings,则设置计划任务以在午夜重命名 Reading 并创建一个新的空文件夹。

然后,您将每天获得一个文件夹,每个文件夹包含数千个文件。

您可以将该方法进一步扩展为按月分组。例如,C:\Reading 变为 c:\Archive\September\22。

您必须注意时间安排,以确保在产品保存到文件夹时不会尝试重命名文件夹。

于 2008-09-22T16:37:09.143 回答
1

要创建一个可以扩展到大量未知文件的文件夹结构,我喜欢以下系统:

将文件名拆分为固定长度的片段,然后为除最后一个片段之外的每个片段创建嵌套文件夹。

该系统的优点是文件夹结构的深度仅与文件名的长度一样深。因此,如果您的文件是按数字序列自动生成的,那么结构就很深了。

12.jpg -> 12.jpg
123.jpg -> 12\123.jpg
123456.jpg -> 12\34\123456.jpg

这种方法确实意味着文件夹包含文件和子文件夹,但我认为这是一个合理的权衡。

这是一个漂亮的PowerShell 单线器,可助您一臂之力!

$s = '123456'

-join  (( $s -replace '(..)(?!$)', '$1\' -replace '[^\\]*$','' ), $s )
于 2014-02-23T22:14:11.243 回答