一个目录中可以放多少个文件?

在一个目录中保存多少文件有关系吗?如果是,一个目录中有多少文件是太多的,拥有太多文件的影响是什么?(这是在Linux服务器上。)

背景:我有一个相册网站,上传的每张图片都被重命名为8位十六进制数字的id(比如,a58f375c.jpg)。这是为了避免文件名冲突(例如,如果上传了大量“IMG0001.JPG”文件)。原始文件名和任何有用的元数据都存储在数据库中。现在,我在images目录中有大约1500个文件。这使得列出目录中的文件(通过FTP或SSH客户端)需要几秒钟的时间。但除此之外,我看不出它还有什么效果。特别是,对于图像文件提供给用户的速度似乎没有任何影响。

我想过通过创建16个子目录来减少图像的数量:0-9和a-f。然后我将根据文件名的第一个十六进制数字将图像移动到子目录中。但是除了偶尔通过FTP/SSH列出目录之外,我不确定这样做是否有任何理由。

369151 次浏览

我遇到的最大问题是在32位系统上。一旦你通过了一个特定的数字,像'ls'这样的工具就会停止工作。

一旦您通过了这个障碍,试图对该目录做任何事情都将成为一个巨大的问题。

问题归结为你将如何处理这些文件。

在Windows下,对于我来说,在资源管理器中打开任何超过2k个文件的目录都比较缓慢。如果它们都是图像文件,在缩略图视图中,超过1k的文件往往打开得非常慢。

系统规定的上限曾一度是32767个。现在它更高了,但即使如此,在大多数情况下,一次处理的文件也太多了。

这在一定程度上取决于Linux服务器上使用的特定文件系统。现在默认是ext3和dir_index,这使得搜索大目录非常快。

所以速度不应该是一个问题,除了你已经注意到的问题,那就是上市需要更长的时间。

一个目录下的文件总数是有限制的。我记得它可以运行到32000个文件。

这实际上取决于所使用的文件系统,以及一些标志。

例如,ext3可以有数千个文件;但在几千次之后,它就变得非常缓慢了。主要是在列出目录时,但也在打开单个文件时。几年前,它获得了“htree”选项,这极大地缩短了给定文件名获取inode所需的时间。

就我个人而言,我使用子目录将大多数级别保持在1000个左右的项目以下。在您的例子中,我将创建256个目录,使用ID的最后两个十六进制数字。使用最后一个数字,而不是第一个数字,这样可以实现负载平衡。

我记得我运行了一个程序,它在输出时创建了大量的文件。每个目录按30000个文件进行排序。当我不得不重用产生的输出时,我不记得有任何读取问题。它是在一台32位的Ubuntu Linux笔记本电脑上,即使是鹦鹉螺也显示了目录内容,尽管要等几秒钟。

ext3文件系统:类似的代码在64位系统上处理每个目录64000个文件。

# EYZ0:

  • 最大文件数:268,173,300
  • 每个目录最大文件数:216 - 1 (65,535)
  • 最大文件大小:2 GiB - 1不带# eyz0,4  GiB - 1带

# EYZ0:

  • 最大文件数:232 - 1 (4,294,967,295)
  • 最大文件大小
    • 实现:244 - 26字节(16 TiB - 64 KiB)
    • 理论:264 - 26字节(16 EiB - 64 KiB)
    • 李< / ul > < / >
    • 最大卷大小
      • 实现:232 - 1 集群(256 TiB - 64 KiB)
      • 理论:264 - 1 clusters (1 YiB - 64 KiB)
      • 李< / ul > < / >

      # EYZ0:

      • 最大文件数:1018
      • 每个目录的最大文件数:~1.3 × 1020.(性能问题超过10,000)
      • 最大文件大小
        • 16 GiB(块大小为1 KiB)
        • 256 GiB(块大小为2 KiB)
        • 2 TiB(块大小为4 KiB)
        • 2 TiB(块大小为8 KiB)
        • 李< / ul > < / >
        • 最大卷大小
          • 4 TiB(块大小为1 KiB)
          • 8 TiB(块大小为2 KiB)
          • 16 TiB(块大小为4 KiB)
          • 32 TiB(块大小为8 KiB)
          • 李< / ul > < / >

          # EYZ0:

          • 最大文件数:min(volumeSize / 213, numberOfBlocks)
          • 最大文件大小:与ext2相同
          • 最大卷大小:与ext2相同

          # EYZ0:

          • 最大文件数:232 - 1 (4,294,967,295)
          • 每个目录的最大文件数:无限制
          • 最大文件大小:244 - 1 字节(16 TiB - 1)
          • 最大卷大小:248 - 1 字节(256 TiB - 1)

如果实现目录分区方案所涉及的时间是最少的,我赞成它。当您第一次调试涉及通过控制台操作10,000个文件目录的问题时,您将能够理解。

例如,F-Spot将照片文件存储为YYYY\MM\DD\filename。ext,这意味着在手动操作我的~20000张照片集合时,我必须处理的最大目录大约有800个文件。这也使文件更容易从第三方应用程序中浏览。永远不要以为只有你的软件会访问你的软件文件。

请记住,在Linux上,如果目录中有太多文件,shell可能无法展开通配符。我在Linux上托管的相册有这个问题。它将所有调整大小的图像存储在一个目录中。虽然文件系统可以处理许多文件,但shell不能。例子:

-shell-3.00$ ls A*
-shell: /bin/ls: Argument list too long

-shell-3.00$ chmod 644 *jpg
-shell: /bin/chmod: Argument list too long

这完全取决于文件系统。许多现代文件系统使用良好的数据结构来存储目录的内容,但旧的文件系统通常只是将条目添加到列表中,因此检索文件是一个O(n)操作。

即使文件系统做得正确,列出目录内容的程序仍然绝对有可能搞砸并执行O(n^2)排序,因此为了安全起见,我总是将每个目录的文件数量限制在不超过500个。

我尊重这并不能完全回答你的问题,多少是太多了,但解决长期问题的一个想法是,除了存储原始文件元数据外,还存储它存储在磁盘上的哪个文件夹-规范化元数据。一旦一个文件夹的增长超出了性能、美观或其他原因的限制,你只需创建第二个文件夹并开始在那里放置文件……

我现在正在研究一个类似的问题。我们有一个层次结构的目录结构,并使用映像id作为文件名。例如,其中放置了一个带有id=1234567的图像

..../45/67/1234567_<...>.jpg

使用最后4位数字来确定文件的位置。

对于几千张图像,您可以使用一级层次结构。出于效率/备份/其他考虑,系统管理员建议在任何给定目录(ext3)中不超过几千个文件。

我也遇到过类似的问题。我试图访问一个有一万多个文件的目录。构建文件列表和在任何文件上运行任何类型的命令花费的时间太长了。

我想了一个小php脚本来为自己做这件事,并试图找出一种方法来防止它在浏览器中超时。

下面是我编写的php脚本来解决这个问题。

列出FTP目录中文件过多的文件

如何帮助别人

我在一个ext3目录中有超过800万个文件。libc readdir()findls和这个线程中讨论的大多数其他方法都使用它来列出大型目录。

在这种情况下,lsfind慢的原因是readdir()一次只读取32K的目录条目,所以在慢磁盘上需要很多很多次读取才能列出一个目录。这个速度问题有一个解决方案。我在http://www.olark.com/spw/2011/08/you-can-list-a-directory-with-8-million-files-but-not-with-ls/上写了一篇非常详细的文章

关键是:直接使用getdents()http://www.kernel.org/doc/man-pages/online/pages/man2/getdents.2.html,而不是基于libc readdir()的任何东西,这样在从磁盘读取目录项时就可以指定缓冲区大小。

我有一个目录,里面有88914个文件。就像你自己,这是用于存储缩略图和在Linux服务器上。

通过FTP或php函数列出的文件是缓慢的,但是在显示文件时也有性能上的影响。例如,www.website.com/thumbdir/gh3hg4h2b4h234b3h2.jpg的等待时间为200-400毫秒。在另一个网站上,我有一个目录下大约100个文件,在大约40毫秒的等待后,图像就显示出来了。

我给出了这个答案,就像大多数人刚刚写了如何执行目录搜索函数一样,你不会在拇指文件夹上使用它——只是静态地显示文件,但会对如何实际使用文件的性能感兴趣。

不管怎样,我只是在ext4文件系统上创建了一个目录,其中有1,000,000个文件,然后通过web服务器随机访问这些文件。我没有注意到访问这些文件比(比如说)只有10个文件有任何溢价。

这是从根本上与我几年前在ntfs上做这件事的经验不同。

不是答案,只是一些建议。

选择一个更合适的FS(文件系统)。因为从历史的角度来看,你们所有的问题都是足够明智的,在过去几十年里曾经是金融服务体系演变的核心。我的意思是更现代的FS更好地支持你的问题。首先从FS列表开始,根据你的最终目的做一个比较决策表。

我认为是时候改变你的思维模式了。所以我个人建议使用分布式系统感知FS,这意味着在大小、文件数量等方面没有任何限制。否则,你迟早会遇到意想不到的新问题。

我不确定这是否有效,但如果您没有提到一些实验,请尝试一下当前文件系统上的AUFS。我想它可以将多个文件夹模拟为单个虚拟文件夹。

为了克服硬件限制,可以使用RAID-0。

Ext3实际上有目录大小限制,它们取决于文件系统的块大小。没有每个目录的文件“最大数量”,而是每个目录的“用于存储文件条目的最大块数量”。具体来说,目录本身的大小不能超过高度为3的b-树,并且树的扇出取决于块大小。有关详细信息,请参见此链接。

https://www.mail-archive.com/cwelug@googlegroups.com/msg01944.html

我最近在一个格式化为2K块的文件系统上遇到了这种问题,当我从另一个ext3文件系统复制时,它莫名其妙地得到了目录满的内核消息warning: ext3_dx_add_entry: Directory index full!。在我的例子中,一个只有480,000个文件的目录无法复制到目标。

没有一个数字是“太多”的,只要它不超过操作系统的限制。然而,不管哪种操作系统,一个目录中的文件越多,访问任何单个文件所需的时间就越长,而且在大多数操作系统上,性能是非线性的,因此从10,000个文件中找到一个文件所需的时间是在1,000个文件中找到一个文件所需的时间的10倍以上。

与目录中有大量文件相关的次要问题包括通配符展开失败。为了降低风险,您可以考虑根据上传日期或其他有用的元数据对目录进行排序。

< p > # EYZ0 < br > 一些用户提到性能影响取决于所使用的文件系统。当然可以。像EXT3这样的文件系统可能非常慢。但是即使你使用EXT4或XFS,你也不能阻止通过lsfind或通过像FTP这样的外部连接列出一个文件夹会变得越来越慢 < p > # EYZ0 < br > 我喜欢和@armandino一样的方式。为此,我使用PHP中的这个小函数将id转换为每个目录1000个文件的文件路径:

function dynamic_path($int) {
// 1000 = 1000 files per dir
// 10000 = 10000 files per dir
// 2 = 100 dirs per dir
// 3 = 1000 dirs per dir
return implode('/', str_split(intval($int / 1000), 2)) . '/';
}

或者你可以使用第二个版本,如果你想使用字母数字字符:

function dynamic_path2($str) {
// 26 alpha + 10 num + 3 special chars (._-) = 39 combinations
// -1 = 39^2 = 1521 files per dir
// -2 = 39^3 = 59319 files per dir (if every combination exists)
$left = substr($str, 0, -1);
return implode('/', str_split($left ? $left : $str[0], 2)) . '/';
}

结果:

<?php
$files = explode(',', '1.jpg,12.jpg,123.jpg,999.jpg,1000.jpg,1234.jpg,1999.jpg,2000.jpg,12345.jpg,123456.jpg,1234567.jpg,12345678.jpg,123456789.jpg');
foreach ($files as $file) {
echo dynamic_path(basename($file, '.jpg')) . $file . PHP_EOL;
}
?>


1/1.jpg
1/12.jpg
1/123.jpg
1/999.jpg
1/1000.jpg
2/1234.jpg
2/1999.jpg
2/2000.jpg
13/12345.jpg
12/4/123456.jpg
12/35/1234567.jpg
12/34/6/12345678.jpg
12/34/57/123456789.jpg


<?php
$files = array_merge($files, explode(',', 'a.jpg,b.jpg,ab.jpg,abc.jpg,ddd.jpg,af_ff.jpg,abcd.jpg,akkk.jpg,bf.ff.jpg,abc-de.jpg,abcdef.jpg,abcdefg.jpg,abcdefgh.jpg,abcdefghi.jpg'));
foreach ($files as $file) {
echo dynamic_path2(basename($file, '.jpg')) . $file . PHP_EOL;
}
?>


1/1.jpg
1/12.jpg
12/123.jpg
99/999.jpg
10/0/1000.jpg
12/3/1234.jpg
19/9/1999.jpg
20/0/2000.jpg
12/34/12345.jpg
12/34/5/123456.jpg
12/34/56/1234567.jpg
12/34/56/7/12345678.jpg
12/34/56/78/123456789.jpg
a/a.jpg
b/b.jpg
a/ab.jpg
ab/abc.jpg
dd/ddd.jpg
af/_f/af_ff.jpg
ab/c/abcd.jpg
ak/k/akkk.jpg
bf/.f/bf.ff.jpg
ab/c-/d/abc-de.jpg
ab/cd/e/abcdef.jpg
ab/cd/ef/abcdefg.jpg
ab/cd/ef/g/abcdefgh.jpg
ab/cd/ef/gh/abcdefghi.jpg

正如你所看到的,# eyz0版本每个文件夹最多包含1000个文件和99个目录,其中包含1000个文件和99个目录……

但是不要忘记,许多目录会导致相同的性能问题!

最后,您应该考虑如何减少文件总数。根据你的目标,你可以使用CSS精灵组合多个小图像,如头像,图标,微笑等,或者如果你使用许多小的非媒体文件,考虑将它们组合在JSON格式。以我为例,我有数千个迷你缓存,最后我决定将它们组合成10个。

上面的大多数答案都没有说明,对于最初的问题,没有“一刀切”的答案。

在今天的环境中,我们有一个大的不同硬件和软件的组合——一些是32位的,一些是64位的,一些是前沿的,一些是可靠的,永不改变的。 除此之外,还有各种新旧硬件、新旧操作系统、不同的供应商(Windows、unix、Apple等)以及伴随而来的无数实用程序和服务器。 随着硬件的改进,软件被转换为64位兼容性,在这个非常庞大而复杂的世界中,让所有的部件都能很好地适应快速变化的步伐,必然会有相当大的延迟

恕我直言,没有一种方法可以解决问题。解决办法是研究各种可能性,然后通过反复试验找到最适合你特定需求的方法。每个用户必须确定什么适合他们的系统,而不是使用千篇一律的方法。

例如,我有一个媒体服务器,其中有一些非常大的文件。结果是只有大约400个文件填满一个3tb的驱动器。仅使用了1%的inode,但使用了总空间的95%。对于其他具有许多较小文件的用户,可能会在inode快要填满空间之前耗尽inode。(在ext4文件系统上,根据经验,每个文件/目录使用1个inode。) 虽然从理论上讲,一个目录中可能包含的文件总数几乎是无限的,但实际情况决定了总体使用情况决定了实际单位,而不仅仅是文件系统能力

我希望以上所有不同的答案都能促进思考和解决问题,而不是成为进步的不可逾越的障碍。

我也有同样的问题。试图在ext4的Ubuntu服务器中存储数百万个文件。结束运行我自己的基准测试。发现平面目录执行得更好,同时使用起来更简单:

benchmark

写了一个文章

完美的,

完美的,

完美无瑕:

(g.m. - rip)

function ff () {
d=$1; f=$2;
p=$( echo $f |sed "s/$d.*//; s,\(.\),&/,g; s,/$,," );
echo $p/$f ;
}




ff _D_   09748abcGHJ_D_my_tagged_doc.json


0/9/7/4/8/a/b/c/G/H/J/09748abcGHJ_D_my_tagged_doc.json




ff -   gadsf12-my_car.json


g/a/d/s/f/1/2/gadsf12-my_car.json

还有这个

ff _D_   0123456_D_my_tagged_doc.json


0/1/2/3/4/5/6/0123456_D_my_tagged_doc.json






ff .._D_   0123456_D_my_tagged_doc.json


0/1/2/3/4/0123456_D_my_tagged_doc.json

享受吧!