NTFS性能和大容量文件和目录

带NTFS的Windows在处理大量文件和目录时表现如何?

在遇到性能问题或其他问题之前,是否有关于可以放置在单个目录中的文件或目录限制的指导?

例如,有一个包含10万个文件夹的文件夹是可以的吗?

137609 次浏览

10万应该没问题。

我曾(轶事)看到人们在处理数百万个文件时遇到问题,我自己也曾在使用Explorer时遇到问题,就是不知道如何计算超过6万多个文件,但NTFS应该对您所谈论的卷很好。

如果你想知道,技术上(我希望理论)最大文件数是:4,294,967,295

对于本地访问,大量的目录/文件似乎不是问题。然而,如果你是通过网络访问它,几百次之后就会有明显的性能下降(特别是从Vista机器访问时(XP到Windows Server w/NTFS在这方面似乎运行得更快)。

当您创建一个包含N个条目的文件夹时,您在文件系统级别创建了一个包含N个条目的列表。这个列表是一个系统范围的共享数据结构。如果开始通过添加/删除条目不断修改这个列表,我预计至少会在共享数据上出现一些锁争用。这个争用——从理论上讲——会对性能产生负面影响。

对于只读场景,我无法想象有大量条目的目录会有任何性能下降的原因。

这里有一些来自某人的建议,在这个环境中,我们的文件夹包含数千万个文件。

  1. 文件夹存储索引信息(链接到子文件&子文件夹)在索引文件中。当你有很多子文件时,这个文件会变得非常大。注意,它没有区分文件夹的子节点和文件的子节点。唯一的区别是子目录的内容是子目录的文件夹索引还是子目录的文件数据。注意:我在某种程度上简化了这一点,但这一点已经很清楚了。
  2. 索引文件将被分割。当它变得太碎片化时,您将无法向该文件夹添加文件。这是因为允许的片段数量是有限制的。这是设计出来的。我已经在微软的事故支持电话中确认过了。因此,尽管理论上一个文件夹中可以拥有的文件数量的限制是数十亿个,但当你开始触及数千万个文件时,你会先达到碎片限制。
  3. 但也不全是坏事。你可以使用工具:contig.exe来整理这个索引。它不会减少索引的大小(对于数千万个文件,可以达到几个Gigs),但可以减少片段的数量。注意:磁盘碎片整理工具不会对文件夹的索引进行碎片整理。它将对文件数据进行碎片整理。只有contig.exe工具将对索引进行碎片整理。供您参考:您也可以使用它来整理单个文件的数据。
  4. 如果你做碎片整理,不要等到你达到最大#碎片限制。我有一个文件夹,我不能碎片整理,因为我已经等到太晚了。我的下一个测试是尝试将一些文件从该文件夹移到另一个文件夹,看看是否可以进行碎片整理。如果这失败了,那么我将不得不做的是1)创建一个新文件夹。2)移动一批文件到新文件夹。3)整理新文件夹。重复#2 ,直到这一步完成,然后4)删除旧文件夹,重命名新文件夹以匹配旧文件夹。

更直接地回答您的问题:如果您正在查看10万个条目,不用担心。请自便。如果你正在查看数千万个条目,那么:

a)计划将它们细分为子文件夹(例如,假设你有100亿个文件。最好把它们存储在1000个文件夹中,这样每个文件夹只有10万个文件,而不是存储在一个大文件夹中。这将创建1000个文件夹索引,而不是一个更有可能达到最大碎片数量限制的大索引

b)制定计划,定期运行contig.exe,以保持大文件夹的索引碎片化。

如果你觉得无聊,就读读下面的文章。

实际的限制不是在片段的#上,而是在存储指向片段的指针的数据段的记录数量上。

因此,您所拥有的是一个数据段,它存储指向目录数据片段的指针。目录数据存储关于子目录的信息&目录应该存储的子文件。实际上,目录并不“存储”任何东西。因为存储介质本身是线性的,所以它只是一个跟踪和表示特性,向用户展示了层次结构的错觉。

还有一些性能问题,因为创建短文件名会降低速度。如果你在[1]文件夹中有超过300k个文件,微软建议关闭短文件名创建。前6个字符越不独特,问题就越大。

[1] NTFS如何工作 from http://technet.microsoft.com,搜索“300,000”

我正在构建一个文件结构来托管多达20亿(2^32)个文件,并执行了以下测试,显示在固态硬盘(SSD)上每个NTFS目录大约250个文件或120个目录时导航+读取性能急剧下降:

  • 在250到1000个文件之间,文件性能下降50%。
  • 当目录个数为120 ~ 1000时,目录性能下降60%。
  • 数值> 1000保持相对稳定

有趣的是,目录和文件的数量并没有显著的影响。

所以教训是:

  • 文件数量超过250的成本系数为2
  • 高于120的目录成本为2.5
  • Windows 7中的文件资源管理器可以处理大的#文件或#Dirs文件,但可用性仍然很差。
  • 引入子目录的成本并不高

这是数据(每个文件和目录2个测量值):

(FOPS = File Operations per Second)
(DOPS = Directory Operations per Second)


#Files  lg(#)   FOPS    FOPS2   DOPS    DOPS2
10   1.00    16692   16692   16421   16312
100   2.00    16425   15943   15738   16031
120   2.08    15716   16024   15878   16122
130   2.11    15883   16124   14328   14347
160   2.20    15978   16184   11325   11128
200   2.30    16364   16052   9866    9678
210   2.32    16143   15977   9348    9547
220   2.34    16290   15909   9094    9038
230   2.36    16048   15930   9010    9094
240   2.38    15096   15725   8654    9143
250   2.40    15453   15548   8872    8472
260   2.41    14454   15053   8577    8720
300   2.48    12565   13245   8368    8361
400   2.60    11159   11462   7671    7574
500   2.70    10536   10560   7149    7331
1000   3.00    9092    9509    6569    6693
2000   3.30    8797    8810    6375    6292
10000   4.00    8084    8228    6210    6194
20000   4.30    8049    8343    5536    6100
50000   4.70    7468    7607    5364    5365

这是测试代码:

[TestCase(50000, false, Result = 50000)]
[TestCase(50000, true, Result = 50000)]
public static int TestDirPerformance(int numFilesInDir, bool testDirs) {
var files = new List<string>();
var dir = Path.GetTempPath() + "\\Sub\\" + Guid.NewGuid() + "\\";
Directory.CreateDirectory(dir);
Console.WriteLine("prepare...");
const string FILE_NAME = "\\file.txt";
for (int i = 0; i < numFilesInDir; i++) {
string filename = dir + Guid.NewGuid();
if (testDirs) {
var dirName = filename + "D";
Directory.CreateDirectory(dirName);
using (File.Create(dirName + FILE_NAME)) { }
} else {
using (File.Create(filename)) { }
}
files.Add(filename);
}
//Adding 1000 Directories didn't change File Performance
/*for (int i = 0; i < 1000; i++) {
string filename = dir + Guid.NewGuid();
Directory.CreateDirectory(filename + "D");
}*/
Console.WriteLine("measure...");
var r = new Random();
var sw = new Stopwatch();
sw.Start();
int len = 0;
int count = 0;
while (sw.ElapsedMilliseconds < 5000) {
string filename = files[r.Next(files.Count)];
string text = File.ReadAllText(testDirs ? filename + "D" + FILE_NAME : filename);
len += text.Length;
count++;
}
Console.WriteLine("{0} File Ops/sec ", count / 5);
return numFilesInDir;
}

在复制一个在线库时,我有过在NTFS目录中复制大约100,000个文件(每个文件数mb)的实际经验。

使用Explorer或7-zip打开该目录大约需要15分钟。

winhttrack编写站点副本总是会在一段时间后卡住。它还处理目录,包含大约100万个文件。我认为最糟糕的事情是MFT只能按顺序遍历。

在ext3的ext2fsd下打开相同的文件,给出了几乎相同的时间。 可能迁移到reiserfs(而不是reiser4fs)会有所帮助

尽量避免这种情况可能是最好的。

对于你自己的程序使用blobs w/o任何fs可能是有益的。 这就是Facebook存储照片的方式