NTFS性能问题和大量文件和目录。

205

Windows采用NTFS文件系统处理大量文件和目录时,性能如何?

在一个单一的目录中放置多少个文件或目录会导致性能问题或其他问题?是否有相关指南?

例如,将 100,000 个文件夹置于同一文件夹中是否可行?


4
如何处理大量的小文件? - Mateen Ulhaq
这个相关问题的答案不如这里被接受的答案。 - Eric J.
这个实现可能很有用:github.com/acrobit/AcroFS - Ghominejad
8个回答

298

这是一个有着数千万文件文件夹的环境下的一些建议:

  1. 一个文件夹会在一个索引文件中存储子文件和子文件夹的索引信息。当你拥有大量的子文件和子文件夹时,这个文件会变得非常大。请注意,它不区分子文件夹和子文件。唯一的区别就是该子项的内容是子文件夹的索引或子文件的数据。注意:我有些简化了情况,但这样可以表达我的意思。
  2. 索引文件会发生碎片化。当它过于碎片化时,您将无法向该文件夹添加文件。这是因为有一个允许的碎片数量限制。这是设计上的。我在一次支持事件电话中已经与微软确认过了。因此,虽然您可以在一个文件夹中拥有数十亿个文件的理论极限,但是当您开始拥有数千万个文件时,您首先会遇到碎片化限制。
  3. 然而,情况并不都是糟糕的。您可以使用工具:contig.exe来对这个索引进行碎片整理。它不会减小索引的大小(对于数千万个文件,它可能会达到几个Gig),但可以减少碎片数量。注意:磁盘碎片整理工具不会整理文件夹的索引。它会整理文件数据。只有contig.exe工具才能整理索引。FYI:您还可以使用该工具来对单个文件的数据进行碎片整理。
  • 如果你想要进行磁盘碎片整理,不要等到碎片数量已经达到上限。我有一个文件夹因为等到了最后才整理,结果现在无法整理。我接下来打算把一些文件从那个文件夹移动到另一个文件夹试试看能否完成整理。如果仍旧失败,那么我需要执行以下步骤:1)创建一个新的文件夹;2)移动一批文件到新文件夹里;3)对新文件夹进行碎片整理;4)重复执行第2和第3步直到完成整理;5)删除旧文件夹并将新文件夹改名为旧文件夹的名称。
  • 针对你的问题,如果你只有100K的文件量,那就不必担心,可以随意处理。但如果文件量达到数千万级别,则需要:

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

    b)计划定期运行contig.exe 来保持大文件夹的索引整洁。

    只有在无聊时才需阅读以下内容:

    实际限制不在于碎片数量,而在于存储指向这些碎片的指针的数据段记录数。

    因此,您拥有存储指向目录数据片段的指针的数据段。目录数据存储关于该目录所存储的子目录和子文件的信息。实际上,目录并没有“存储”任何东西。它只是一个跟踪和展示功能,为用户呈现层次结构的幻象,因为存储介质本身是线性的。


    7
    我该在哪里找到有关 contig.exe 的更多信息,它不在我的服务器上。谷歌搜索返回了 这个 technet 页面,但没有提到子目录或文件夹索引碎片整理。 - Evan Carroll
    41
    我从与微软工程师的技术通话中了解到了连续块和文件夹索引碎片化。在经历了他们无用的1-3级技术支持层之后,这真是一件非常痛苦的事情。(咳咳...你尝试过运行 chkdsk 吗?你可以尝试在 Windows Explorer 中打开文件夹吗?你能检查文件夹权限吗?)傻瓜!我可不想坐在这里等上七天让你该死的 chkdsk 扫描数千万个文件的驱动器!! - MrB
    7
    请运行contig.exe并指向一个目录,我认为这将完成工作:输入contig -a .,得到以下结果:C:\temp\viele-Dateien分为411个碎片。摘要: 处理的文件数:1 平均碎片数:411个/文件。 - Lumi
    2
    这个问题在SSD硬盘上仍然存在吗?我需要创建一个包含大量快捷方式的文件夹(约6百万个)。我在另一个较小的文件夹上尝试了contig.exe,发现它非常碎片化(1075个碎片),但contig无法对其进行碎片整理。 - GPhilo
    6
    @GPhilo 我可以证实,当使用数百万个文件时,SSD 的性能仍会下降。我也尝试过对该文件夹进行碎片整理,但 contig 对其没有任何作用。它表现得好像已经完成了,但是运行前后显示的碎片情况相同。 - Bram Vanroy
    显示剩余7条评论

    53

    在创建短文件名时,也存在性能问题会拖慢系统速度。如果您在一个文件夹中有超过300k个文件,微软建议关闭短文件名的创建[1]。前6个字符越不唯一,问题就越突出。

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


    7
    如果你在一个NTFS文件夹中使用大量文件(300,000个或更多),为了获得更好的性能,特别是如果长文件名的前六个字符相似,应禁用短文件名生成。这里附上一句引用:“如果你在一个NTFS文件夹中使用大量文件(300,000个或更多),为了获得更好的性能,特别是如果长文件名的前六个字符相似,应禁用短文件名生成。”顺便提一下,输入“300”就足够了(无需复制到剪贴板)。 - Wolf

    41
    我正在构建一个文件结构,可以托管多达20亿(2^32)个文件,并进行了以下测试,显示在单个NTFS目录上的文件数达到250个或120个目录时,文件导航和读取性能急剧下降,这是在固态硬盘(SSD)上进行测试的:
    • 250至1000个文件之间,文件性能下降50%。
    • 120至1000个目录之间,目录性能下降60%。
    • 大于1000的数量值相对稳定。
    有趣的是,目录和文件的数量并没有明显干扰。
    所以,教训如下:
    • 超过250个文件需要花费2倍的成本。
    • 超过120个目录需要花费2.5倍的成本。
    • Windows 7中的文件资源管理器可以处理大量的文件或目录,但可用性仍然很差。
    • 引入子目录并不昂贵。
    这是数据(每个文件和目录的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; 
    }
    

    7
    在处理超过 2^8 个文件时,你会看到性能损失,因为你需要禁用短文件名生成(生成 8 个字符的文件名)。详见 https://technet.microsoft.com/zh-cn/library/cc781134(v=ws.10).aspx。 - Kyle Falconer
    1
    你好,我尝试使用以下命令行: fsutil.exe behavior set disable8dot3 1 重启后,对于少于10000个文件/目录,结果基本相同。文章说这只对更高的数字很重要。 但我看到的是一般性能下降,可能是由于我的固态硬盘负载因子更高(现在已经占用80%,而不是45%)。 - Spoc
    非常有用,谢谢。其他用户提出的数百万的估计与实际数值相差甚远。 - Adrian Maire
    2
    即使禁用了8.3名称生成,您仍然需要剥离现有的8.3名称,否则对于现有文件的枚举将会有很小的改进。 - Stephen R
    3
    更多细节请参考:https://blogs.technet.microsoft.com/josebda/2012/11/13/windows-server-2012-file-server-tip-disable-8-3-naming-and-strip-those-short-names-too/ - Stephen R
    3
    NTFS将目录存储为B树。当B树由于增长而变得更深一级时,性能发生急剧变化的那些点仅仅是简单的。这些点可能会因文件名长度而异(因为NTFS试图在每个4K B-tree节点中容纳尽可能多的条目,并且文件名长度确定每个条目的大小),还有如果启用了短名称(因为然后NTFS可能不得不为每个文件添加两个条目而不仅仅是一个)。 - Craig Barkhouse

    16

    10万应该足够了。

    我(仅凭经验)观察到有人在处理数百万个文件时出现问题,我自己也曾遇到过资源管理器无法计算超过6万多个文件的情况,但对于你所讨论的存储量,NTFS 应该能够胜任。

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


    7
    对于未了解此概念的人来说,这个大数字是指(2^32 - 1)个文件。 - meatspace

    8

    对于本地访问,大量的目录/文件似乎不是问题。 但是,如果您通过网络访问它,则在几百个后会出现明显的性能损失(特别是从Vista机器访问)。 (从XP到Windows Server w / NTFS似乎在这方面运行得更快)。


    4
    你确定这是NTFS(服务器上的磁盘协议),而不是SMB(网络层)吗? - MSalters
    不,我没有进行进一步的研究来缩小原因范围。我所拥有的唯一信息就是如上所述。 - Brian Knoblauch

    2

    我曾经在一个目录中处理大约10万个文件(每个文件大小几MB),这些文件都存储在NTFS文件系统中,当我在复制一个在线库时遇到了这个问题。

    使用资源管理器或7-zip打开这个目录需要大约15分钟的时间。

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

    在ext3上使用ext2fsd打开相同的文件需要几乎相同的时间。也许转移到reiserfs(而不是reiser4fs)可以有所帮助。

    试图避免这种情况可能是最好的选择。

    对于使用没有任何文件系统的二进制大对象的自己的程序可能是有益的。这就是Facebook用于存储照片的方式。


    我不确定你从哪里得到了“MFT只能按顺序遍历”的说法?MFT包含一个B树,可以像B树一样遍历。 - phuclv

    2
    当您创建一个包含N个条目的文件夹时,您在文件系统级别上创建了一个包含N个项目的列表。这个列表是一个系统范围内共享的数据结构。如果您不断地通过添加/删除条目来修改此列表,我预计会对共享数据产生一些锁竞争。理论上,这种竞争可能会对性能产生负面影响。
    对于只读场景,我无法想象有任何原因导致具有大量条目的目录性能下降。

    0

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