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

Background: I have a photo album website, and every image uploaded is renamed to an 8-hex-digit id (say, a58f375c.jpg). This is to avoid filename conflicts (if lots of "IMG0001.JPG" files are uploaded, for example). The original filename and any useful metadata is stored in a database. Right now, I have somewhere around 1500 files in the images directory. This makes listing the files in the directory (through FTP or SSH client) take a few seconds. But I can't see that it has any effect other than that. In particular, there doesn't seem to be any impact on how quickly an image file is served to the user.

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


当前回答

“取决于文件系统” 一些用户提到性能影响取决于所使用的文件系统。当然可以。像EXT3这样的文件系统可能非常慢。但是即使您使用EXT4或XFS,也不能防止通过ls或查找或通过FTP等外部连接列出文件夹会变得越来越慢。

解决方案 我喜欢和@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-version每个文件夹最多包含1000个文件和99个目录,其中包含1000个文件和99个目录…

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

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

其他回答

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

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

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

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

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

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

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

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

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

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

In today's environment we have a large conglomerate of different hardware and software -- some is 32 bit, some is 64 bit, some is cutting edge and some is tried and true - reliable and never changing. Added to that is a variety of older and newer hardware, older and newer OSes, different vendors (Windows, Unixes, Apple, etc.) and a myriad of utilities and servers that go along. As hardware has improved and software is converted to 64 bit compatibility, there has necessarily been considerable delay in getting all the pieces of this very large and complex world to play nicely with the rapid pace of changes.

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

I for example have a media server with a few very large files. The result is only about 400 files filling a 3 TB drive. Only 1% of the inodes are used but 95% of the total space is used. Someone else, with a lot of smaller files may run out of inodes before they come near to filling the space. (On ext4 filesystems as a rule of thumb, 1 inode is used for each file/directory.) While theoretically the total number of files that may be contained within a directory is nearly infinite, practicality determines that the overall usage determine realistic units, not just filesystem capabilities.

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

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