你如何处理许多小文件?

时间:2008-09-22 16:24:20

标签: windows-xp filesystems ntfs

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

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

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

14 个答案:

答案 0 :(得分:29)

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

在此设置生效之前需要重新启动。

答案 1 :(得分:25)

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

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

答案 2 :(得分:9)

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

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

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

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

答案 3 :(得分:5)

我已经看到过去通过将文件分割成目录的嵌套层次结构,例如,首先是文件名的第二个字母;那么每个目录都不包含过多的文件。但是,操纵整个数据库仍然很慢。

答案 4 :(得分:4)

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

另外,您是否可以将比一年前更早的文件移动到另一个(但仍可访问)的位置?

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

答案 5 :(得分:4)

你可以尝试使用像Solid File System这样的东西。

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

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

答案 6 :(得分:3)

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

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

答案 7 :(得分:3)

在一个目录中拥有数十万个文件确实会使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个文件。

答案 8 :(得分:3)

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

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

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

答案 9 :(得分:2)

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

就个人而言,我会开发一个应用程序,使该文件夹的界面保持不变,即所有文件都显示为单个文件。然后在应用程序背景中实际上采用这些文件并将它们组合成一个更大的文件(因为大小总是64k,所以你需要的数据应该相对容易)来摆脱你所拥有的混乱。

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

答案 10 :(得分:1)

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

答案 11 :(得分:1)

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

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

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

使用像'find'这样的工具(在cygwin或mingw下)可以在浏览文件时使子目录树不存在问题。

答案 12 :(得分:1)

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

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

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

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

您必须小心时间,以确保在产品保存时不要重命名文件夹。

答案 13 :(得分:0)

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

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

这个系统的优点是文件夹结构的深度只会增加到文件名长度的深度。因此,如果您的文件是以数字顺序自动生成的,那么结构只需要很深。

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

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

这里有一个漂亮的 PowerShell单线程,可以帮助您前进!

$s = '123456'

-join  (( $s -replace '(..)(?!$)', '$1\' -replace '[^\\]*$','' ), $s )