我们如何处理许多小文件?

时间:2020-03-06 14:32:58  来源:igfitidea点击:

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

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

有没有一种方法可以优化NTFS或者Windows,使其可以处理所有这些小文件?

解决方案

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

另外,我们可以将比一年还早的文件移动到其他位置(但仍可访问)吗?

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

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

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

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

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

目录中有10,000个文件后,NTFS性能将严重下降。我们要做的是在目录层次结构中创建一个添加级别,每个子目录包含10,000个文件。

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

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

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

因此,我们仍然可以使他们轻松访问所需的文件,而且还可以让我们更好地控制所有内容的结构。

我们可以尝试使用类似Solid File System的工具。

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

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

如果数据有任何有意义的,分类的方面,则可以将它们嵌套在目录树中。我认为,速度下降是由于一个目录中的文件数量而不是文件本身的数量所致。

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

即使我们能够改善文件系统/文件浏览器的性能,听起来这又是一个问题,我们将在另外2年或者3年内遇到……仅查看0.3-1mil个文件的清单就会这是一项成本,因此从长远来看,找到只查看较小文件子集的方法可能会更好。

使用" find"(在cygwin或者mingw下)之类的工具可以使浏览文件时不会出现子目录树。

性能问题是由单个目录中的大量文件引起的:一旦消除了这一点,就可以了。这不是特定于NTFS的问题:实际上,大型UNIX系统上的用户主目录/邮件文件经常遇到此问题。

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

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

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

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

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

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

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

我们必须谨慎安排时间,以确保在产品保存到文件夹时不要尝试重命名该文件夹。

在单个目录中拥有成千上万个文件确实会使NTFS瘫痪,实际上我们无能为力。我们应该重新考虑以一种更实用的格式存储数据,例如一个大的tarball或者存储在数据库中。

如果每次阅读确实需要一个单独的文件,则应将它们分类到几个子目录中,而不要将所有子目录都放在同一个目录中。我们可以通过创建目录层次结构并根据文件名将文件放在不同的目录中来进行此操作。这样,我们仍然可以只知道文件名就可以存储和加载文件。

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

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。

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

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

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

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

必须重新启动才能使此设置生效。