我保留在一个目录中的文件数量是否重要?如果是这样,目录中有多少文件太多,文件太多会有什么影响? (这是在Linux服务器上。)
背景:我有一个相册网站,上传的每个图片都重命名为8位十六进制数字(例如a58f375c.jpg)。这是为了避免文件名冲突(例如,如果上传了大量“IMG0001.JPG”文件)。原始文件名和任何有用的元数据都存储在数据库中。现在,我在images目录中有大约1500个文件。这使得列出目录中的文件(通过FTP或SSH客户端)需要几秒钟。但我看不出它除此之外还有什么影响。特别是,对图像文件向用户提供的速度似乎没有任何影响。
我考虑通过制作16个子目录来减少图像数量:0-9和a-f。然后我会根据文件名的第一个十六进制数字将图像移动到子目录中。但我不确定是否有任何理由这样做,除了偶尔通过FTP / SSH列出目录。
答案 0 :(得分:688)
答案 1 :(得分:176)
我在一个ext3目录中有超过800万个文件。 libc readdir()
由find
,ls
和此线程中讨论的大多数其他方法用于列出大型目录。
ls
和find
在这种情况下运行缓慢的原因是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()
的任何内容,这样您就可以在从磁盘读取目录条目时指定缓冲区大小。
答案 2 :(得分:56)
它取决于Linux服务器上使用的特定文件系统。现在默认是使用dir_index的ext3,这使得搜索大目录非常快。
所以速度不应该是一个问题,除了你已经注意到的那个,这个列表需要更长的时间。
一个目录中的文件总数有限制。我似乎记得它肯定能够处理32000个文件。
答案 3 :(得分:56)
我有一个包含88,914个文件的目录。像你一样,它用于存储缩略图和Linux服务器。
通过FTP或php函数列出的文件很慢,但是在显示文件时也会出现性能损失。例如www.website.com/thumbdir/gh3hg4h2b4h234b3h2.jpg的等待时间为200-400毫秒。作为另一个网站的比较,我在一个目录中有大约100个文件,在等待约40ms之后显示图像。
我已经给出了这个答案,因为大多数人刚刚写了目录搜索功能将如何执行,你不会在拇指文件夹上使用 - 只是静态显示文件,但是会对文件的执行方式感兴趣实际使用。
答案 4 :(得分:47)
请记住,在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
答案 5 :(得分:22)
我正在研究类似的问题。我们有一个层次结构的目录结构,并使用图像ID作为文件名。例如,id=1234567
的图片放在
..../45/67/1234567_<...>.jpg
使用最后4位数字来确定文件的位置。
使用几千个图像,您可以使用一级层次结构。我们的系统管理员建议在任何给定目录(ext3)中只有几千个文件用于效率/备份/其他任何原因。
答案 6 :(得分:16)
为了它的价值,我刚刚在ext4
文件系统上创建了一个目录,其中包含1,000,000个文件,然后通过Web服务器随机访问这些文件。我没有注意到访问那些(例如)那里只有10个文件的任何溢价。
这与完全不同于我几年前在ntfs
上执行此操作的经验。
答案 7 :(得分:12)
我遇到的最大问题是32位系统。一旦你传递了一定数量,像'ls'这样的工具就会停止工作。
一旦通过该障碍,尝试对该目录执行任何操作都会成为一个巨大的问题。
答案 8 :(得分:6)
这实际上取决于所使用的文件系统,还有一些标志。
例如,ext3可以包含数千个文件;但是在成千上万之后,它过去很慢。主要是在列出目录时,也是在打开单个文件时。几年前,它获得了“htree”选项,大大缩短了获取带有文件名的inode所需的时间。
就个人而言,我使用子目录将大多数级别保留在大约一千个项目之下。在您的情况下,我将创建256个目录,其中包含ID的两个最后十六进制数字。使用最后一位而不是第一位数字,这样就可以实现负载平衡。
答案 9 :(得分:6)
绝对取决于文件系统。许多现代文件系统使用不错的数据结构来存储目录的内容,但是较旧的文件系统通常只是将条目添加到列表中,因此检索文件是O(n)操作。
即使文件系统做得正确,列出目录内容的程序仍然绝对可能搞乱并进行O(n ^ 2)排序,所以为了安全起见,我总是限制数量每个目录的文件不超过500个。
答案 10 :(得分:5)
如果实现目录分区方案所涉及的时间很少,我赞成。第一次必须调试涉及通过控制台操作10000文件目录的问题时,您将理解。
例如,F-Spot将照片文件存储为YYYY \ MM \ DD \ filename.ext,这意味着我必须处理的最大目录,而手动操作我的~20000照片集大约是800个文件。这也使得文件更容易从第三方应用程序中浏览。永远不要假设您的软件是唯一可以访问软件文件的东西。
答案 11 :(得分:4)
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个文件的目录无法复制到目的地。
答案 12 :(得分:4)
问题归结为你要对这些文件做些什么。
在Windows下,任何包含2k以上文件的目录都会在资源管理器中慢慢打开。如果它们都是图像文件,那么在缩略图视图中,超过1k的打开速度会非常慢。
有一段时间,系统施加的限制是32,767。它现在更高了,但即便如此,在大多数情况下,一次只能处理太多文件。
答案 13 :(得分:3)
答案 14 :(得分:3)
我记得运行一个在输出端创建大量文件的程序。文件按每个目录30000排序。我不记得在重用生成的输出时有任何读取问题。它是在32位Ubuntu Linux笔记本电脑上,甚至Nautilus显示目录内容,尽管几秒钟后。
ext3 filesystem:64位系统上的类似代码处理每个目录64000个文件。
答案 15 :(得分:2)
我更喜欢@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
正如您所看到的$int
- 版本,每个文件夹最多包含1000个文件,最多99个目录包含1000个文件和99个目录......
但不要忘记,许多目录可以加快您的备份过程。您可以随意为每个目录测试1000到10000个文件,但不要添加更多文件,因为如果您希望按文件读取目录文件(ftp客户端,文件读取功能等),则访问时间会非常长。
最后,您应该考虑如何减少总计的文件数量。根据您的目标,您可以使用CSS精灵来组合多个微小的图像,如头像,图标,表情符号等,或者如果您使用许多小型非媒体文件,请考虑将它们组合在一起,例如:以JSON格式。在我的情况下,我有成千上万的迷你缓存,最后我决定将它们组合成10个包。
答案 16 :(得分:2)
我遇到了类似的问题。我试图访问一个包含超过10,000个文件的目录。构建文件列表并在任何文件上运行任何类型的命令都需要很长时间。
我想了一个小PHP脚本为自己做这个,并试图想办法防止它在浏览器中超时。
以下是我为解决此问题而编写的php脚本。
Listing Files in a Directory with too many files for FTP
它如何帮助某人
答案 17 :(得分:2)
我认为这并不能完全回答你的问题,因为有多少是太多,但解决长期问题的一个想法是,除了存储原始文件元数据外,还要存储磁盘上存储的文件夹in - 规范化那段元数据。一旦文件夹增长超出某个限制,您就会对性能,美观或任何原因感到满意,您只需创建第二个文件夹并开始删除文件...
答案 18 :(得分:1)
上面的大部分答案都没有显示出来的是没有&#34; One Size Fits All&#34;回答原来的问题。
在今天的环境中,我们拥有一个由不同硬件和软件组成的大型企业集团 - 一些是32位,一些是64位,一些是最先进的,一些是经过验证的 - 可靠且永不改变。 除此之外,还有各种较旧和较新的硬件,较旧和较新的操作系统,不同的供应商(Windows,Unix,Apple等)以及无数的实用程序和服务器。 随着硬件的改进和软件转换为64位兼容性,将这个非常大而复杂的世界的所有部分与快速变化的速度很好地结合起来必然会有相当大的延迟。
恕我直言,没有办法解决问题。解决方案是研究可能性,然后通过反复试验找到最适合您特定需求的方法。每个用户必须确定哪些适用于他们的系统,而不是使用cookie切割器方法。
例如,我有一个带有一些非常大的文件的媒体服务器。结果只有大约400个文件填充3 TB驱动器。仅使用1%的inode,但使用了95%的总空间。其他人,有很多较小的文件可能会在它们接近填充空间之前耗尽inode。 (在ext4文件系统上,根据经验,每个文件/目录使用1个inode。) 虽然从理论上讲,目录中可能包含的文件总数几乎是无限的,但实用性决定了整体使用情况决定了现实单位,而不仅仅是文件系统功能。我希望上面所有不同的答案都能促进思考和解决问题,而不是为进步提供不可逾越的障碍。
答案 19 :(得分:0)
没有单个数字“太多”,只要它不超过操作系统的限制。但是,目录中的文件越多,无论操作系统如何,访问任何单个文件所需的时间越长,并且在大多数操作系统上,性能都是非线性的,因此要查找10,000个文件中的一个文件需要的时间超过10倍然后在1000中找到一个文件。
与目录中包含大量文件相关的次要问题包括通配符扩展失败。为降低风险,您可以考虑按上载日期或其他一些有用的元数据排序目录。
答案 20 :(得分:0)
不是答案,只是一些建议。
选择更合适的FS(文件系统)。从历史的角度来看,你所有的问题都是足够明智的,成为几十年来不断发展的FS的核心。我的意思是更现代的FS更好地支持你的问题。首先根据FS list的最终目的制作比较决策表。
我认为是时候改变你的范式了。所以我个人建议使用distributed system aware FS,这意味着对大小,文件数量等没有任何限制。否则你迟早会遇到新的意外问题。
我不确定是否有效,但如果您没有提及某些实验,请尝试将AUFS放在当前的文件系统上。我想它可以将多个文件夹模仿为一个虚拟文件夹。
要克服硬件限制,您可以使用RAID-0。
答案 21 :(得分:-1)
完美无瑕,
完美无瑕,
绝对完美:
( 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
享受吧!