题 在文件系统中存储一百万个图像


我有一个项目,将生成大量的图像。大约1,000,000开始。它们不是大图像,所以我会在开始时将它们全部存储在一台机器上。

您如何有效地存储这些图像? (目前是NTFS文件系统)

我正在考虑一个命名方案......首先,所有图像都将从1开始增加名称 我希望这可以帮助我在以后根据需要对它们进行排序,并将它们放在不同的文件夹中。

什么是更好的命名方案:

a / b / c / 0 ... z / z / z / 999

要么

a / b / c / 000 ...... z / z / z / 999

对此有何想法?


75
2017-12-17 16:52




它们是与特定用户绑定还是仅仅是通用的?它们是以任何方式分组的吗?
只是通用的。一些技术设备生成的图像。我正在从1开始逐渐命名它们,只是想知道时间的关系。 - s.mihai
他们将如何使用/访问?通过一个定制的应用程序或什么? - dove
这是你吗? i46.tinypic.com/1z55k7q.jpg
:))是啊... 1密耳。色情图片:)) - s.mihai


答案:


我建议使用常规文件系统而不是数据库。使用文件系统比数据库更容易,您可以使用普通工具来访问文件,文件系统是为这种用法而设计的.NTFS应该可以很好地用作存储系统。

不要将实际路径存储到数据库。最好将图像的序列号存储到数据库,并具有可以从序列号生成路径的功能。例如:

 File path = generatePathFromSequenceNumber(sequenceNumber);

如果您需要更改目录结构,则更容易处理。也许你需要将图像移动到不同的位置,也许你的空间不足,你开始将一些图像存储在磁盘A上,一些图像存储在磁盘B上等。更改一个功能比更改数据库中的路径更容易。

我会使用这种算法来生成目录结构:

  1. 首先用前导零序列号码,直到你有至少12位数的字符串。这是您的文件的名称。您可能想要添加后缀:
    • 12345  - > 000000012345.jpg
  2. 然后将字符串拆分为2或3个字符块,其中每个块表示目录级别。拥有固定数量的目录级别(例如3):
    • 000000012345  - > 000/000/012
  3. 将文件存储在生成的目录下:
    • 因此,具有序列ID的文件的完整路径和文件文件名 123 是 000/000/012/00000000012345.jpg
    • 对于具有序列ID的文件 12345678901234 路径将是 123/456/789/12345678901234.jpg

关于目录结构和文件存储需要考虑的一些事项:

  • 上面的算法为您提供了一个系统,其中每个叶子目录最多有1000个文件(如果您的文件总数少于1 000 000 000 000个)
  • 例如,可能限制目录可以包含的文件和子目录的数量 Linux上的ext3文件系统 每个目录限制31998个子目录。
  • 如果每个目录有大量文件(> 1000),普通工具(WinZip,Windows资源管理器,命令行,bash shell等)可能无法正常工作
  • 目录结构本身会占用一些磁盘空间,因此您不需要太多目录。
  • 使用上述结构,如果您碰巧弄乱了目录结构,只需查看文件名就可以找到图像文件的正确路径。
  • 如果需要从多台计算机访问文件,请考虑通过网络文件系统共享文件。
  • 如果删除大量文件,上述目录结构将不起作用。它在目录结构中留下了“漏洞”。但由于你没有删除任何文件,它应该没问题。

70
2017-12-17 17:32



很有意思!分割文件名...我没想到。我认为这是优雅的做法: - ? - s.mihai
使用散列(例如MD5)作为文件的名称以及目录分发将起作用。文件的完整性不仅对命名方案有利(易于检查),而且您将在整个目录层次结构中具有合理均匀的分布。因此,如果您有一个名为“f6a5b1236dbba1647257cc4646308326.jpg”的文件,则将其存储在“/ f / 6”(或根据您的要求)。 2级深度提供256个目录,或者对于初始1m文件,每个目录只有不到4000个文件。将重新分配自动化到更深层的方案也很容易。
+1我刚刚注意到这个答案与我刚刚发布的答案类似。 - 3dinfluence
我绝对同意使用filessystem并创建一个artficial标识符来“切片”到文件夹名称。但是你也应该尝试获得标识符的随机分布,即不要使用序列号。这将允许您有一个更平衡的文件夹树。此外,通过随机分发,您可以更轻松地跨多个文件系统对树进行分区。我还使用基于ZFS的SAN,启用了重复数据删除,并为每个文件系统使用稀疏卷。您仍然可以通过使用iSCSI访问SAN来使用NTFS。 - Michael Dillon
如果在步骤2中从右向左移动,则文件均匀分布。此外,您不必担心您没有填充足够的零,因为您可以无限数量的文件 - ropo


我将把我的2美分价值放在一条负面建议上:不要使用数据库。

我多年来一直在使用图像存储数据库:大型(1兆 - > 1演出)文件,经常更改,文件的多个版本,经常合理访问。您遇到的大型文件遇到的数据库问题处理起来非常繁琐,编写和交易问题很棘手,您遇到可能导致主要列车的锁定问题 沉船。我在编写dbcc脚本方面有更多的练习,并且从备份恢复表比任何普通人都要多 曾经 有。

我使用过的大多数新系统都将文件存储推送到文件系统,并且只依赖于数据库而不仅仅是索引。文件系统旨在实现这种滥用,它们更容易扩展,如果一个条目被破坏,您很少会丢失整个文件系统。


29
2017-12-17 17:12



是。注意事项! - s.mihai
您是否查看过SQL 2008的FILESTREAM数据类型?它是数据库和文件系统存储之间的交叉。 - NotMe
因为您正在进行快速且不频繁的IO操作,因此坚持使用文件服务器而不是数据库。
如果您只是为每个数据库存储几百个文档或图片怎么办?使用数据库存储的任何缺点是什么? - Beep beep
+1 ......文件系统无论如何都是一种“数据库”(肯定是ntfs),所以为什么要让它过于复杂。 - akira


我认为大多数必须处理此问题的网站都使用某种哈希来确保文件在文件夹中均匀分布。

所以说你有一个像这样的文件的哈希 515d7eab9c29349e0cde90381ee8f810
您可以将它存储在以下位置,您可以使用多少级别来保持每个文件夹中的文件数量较低。
\51\5d\7e\ab\9c\29\349e0cde90381ee8f810.jpg

我已经看过很多次这种方法。您仍然需要一个数据库来将这些文件哈希映射到人类可读的名称以及您需要存储的其他元数据。但是这种方法可以很好地扩展b / c,你可以开始在多台计算机和/或存储池之间分配哈希地址空间等。


12
2017-12-17 20:17



Git使用类似的方法: git-scm.com/book/en/v2/Git-Internals-Git-Objects (支持这个答案) - aexl


理想情况下,您应该对各种结构的随机访问时间运行一些测试,因为您的特定硬盘设置,缓存,可用内存等可以更改这些结果。

假设您可以控制文件名,我会将它们分配到每个目录1000s的级别。您添加的目录级别越多,刻录的inode越多,因此这里有推送。

例如。,

/根/ [0-99] / [0-99] /文件名

注意, http://technet.microsoft.com/en-us/library/cc781134(WS.10).aspx 有关于NTFS设置的更多详细信息。特别是,“如果在NTFS文件夹中使用大量文件(300,000或更多),请禁用短文件名生成以获得更好的性能,特别是如果长文件名的前六个字符相似。”

您还应该考虑禁用不需要的文件系统功能(例如,上次访问时间)。 http://www.pctools.com/guides/registry/detail/50/


11
2017-12-17 17:01



+1用于禁用8.3文件名生成和上次访问时间;当我阅读“大量[文件]”和“NTFS”(Windows)时,这些是我想到的第一件事。 - rob
链接........................ - Pacerier


无论你做什么,都不要将它们全部存储在一个目录中。

根据这些图像名称的分布,您可以创建一个目录结构,其中您有单字母顶级文件夹,其中您将有另一组子文件夹用于第二个字母的图像等。

所以:

img\a\b\c\d\e\f\g\ 将包含以'abcdefg'开头的图像,依此类推。

您可以介绍自己需要的适当深度。

这个解决方案的好处是目录结构有效地像哈希表/字典。给定一个图像文件名,您将知道它的目录并给出一个目录,您将知道那里的图像子集。


7
2017-12-17 16:58



\ a \ b \ c \ d \ e \ f \我现在在做,我在想有一种明智的方法可以做到这一点。 - s.mihai
这是一种普遍接受的如何物理存储它们的解决方案。显然,生成图像URL是可以根据图像文件名称动态轻松完成的。此外,为了提供服务,您甚至可以在图像服务器上引入img-a,img-b子域,以加快加载时间。
+1表示“不要将它们全部存储在一个目录中”。我支持一个遗留系统,它在一个文件夹中将超过47000个文件放在服务器上,而资源管理器只需要一分钟就可以打开该文件夹。 - Mark Ransom
执行\ b \ c \ d \ e \ f \ g会使目录结构非常深,每个目录只包含很少的文件。最好每个目录级别多使用一个字母,例如ab \ cd \ ef \或abc \ def \。目录也占用磁盘空间,因此您不需要太多空间。 - Juha Syrjälä
我不得不在一个目录中支持一个包含4 +百万个文件的应用程序;它工作得非常好,但你永远不会让资源管理器打开文件夹,它会不断地对新增内容进行排序。 NTFS的+1能够处理它而不会死亡。 - SqlACID


我会将这些存储在文件系统上,但这取决于文件数量的增长速度。这些文件是否托管在网络上?有多少用户可以访问这些文件?在我给你更好的建议之前,这些是需要回答的问题。我也会从Facebook看Haystack,他们有一个非常好的存储和提供图像的解决方案。

此外,如果选择文件系统,则需要使用目录对这些文件进行分区。我一直在研究这个问题并提出了一个解决方案,但它绝不是一个完美的解决方案。我通过哈希表和用户进行分区,你可以阅读更多关于我的内容 博客


5
2017-12-17 16:59



图像不适合频繁访问。所以没有问题。他们的人数会增长很快。我假设将有1密耳。在1个月内标记。 - s.mihai
我对程序员的观点很感兴趣,所以我不会过多地思考这个问题 - s.mihai
因此,如果您不需要快速访问,Haystack可能不适合您。在我看来,使用目录分区是最简单的解决方案。 - Lukasz


我们有一个拥有400万张图片的照相馆系统。我们仅将数据库用于元数据,并使用反向命名系统将所有图像存储在文件系统中,其中文件夹名称从文件的最后一位生成,最后一位,依此类推。例如。: 000001234.jpg存储在目录结构中,如4 \ 3 \ 2 \ 1 \ 000001234.jpg。

这种方案在数据库中与身份索引很好地配合,因为它可以均匀地填充整个目录结构。


5
2017-12-30 22:10





快点,您不需要在DB中存储文件路径。如果您的文件以您描述的方式命名,则可以存储数值。然后使用已经讨论过的明确定义的存储方案之一,您可以将索引作为数字获取,并通过遍历目录结构快速找到该文件。


4
2017-12-17 17:18



: - ?好快点。就是说现在我没有生成路径的算法。 - s.mihai


新的MS SQL 2008有一个新功能来处理这种情况,它被称为FILESTREAM。看一看:

Microsoft TechNet FILESTREAM概述


4
2017-12-17 17:24





您的图像是否需要唯一命名?  生成这些图像的进程可以多次生成相同的文件名吗?很难说不知道什么设备正在创建文件名但是说设备是'重置'并且在重新启动时它开始命名图像,就像上次'重置'一样 - 如果这是一个问题..

另外,你说你将在一个月内拍摄100万张图像。那之后怎么样? 这些图像继续填充文件系统的速度有多快?  它们会在某个时刻达到顶峰,并在大约100万个TOTAL图像或其中达到平衡 一个月又一个月会继续增长和成长吗? 

我问,因为你可以按月开始设计文件系统,然后按图像开始。我可能倾向于建议您将图像存储在这样的目录结构中:

imgs\yyyy\mm\filename.ext

where: yyyy = 4 digit year
         mm = 2 digit month

example:  D:\imgs\2009\12\aaa0001.jpg
          D:\imgs\2009\12\aaa0002.jpg
          D:\imgs\2009\12\aaa0003.jpg
          D:\imgs\2009\12\aaa0004.jpg
                   |
          D:\imgs\2009\12\zzz9982.jpg
          D:\imgs\2010\01\aaa0001.jpg (this is why I ask about uniqueness)
          D:\imgs\2010\01\aab0001.jpg

对于安全类型的图像,月,年,甚至日都是好的。不确定这是不是你正在做的事情但是我用一个家庭安全摄像头每隔10秒拍摄一张照片......这样你的应用程序可以深入到特定的时间甚至可能认为图像生成的范围。或者,而不是年,月 - 是否有一些其他“意义”可以从图像文件本身派生?除了我提供的日期示例之外的其他一些描述符?

我不会将二进制数据存储在DB中。这种事情从未有过良好的表现/运气。无法想象它与100万张图像一起运作良好。我会存储文件名,就是这样。如果它们都是JPG,那么甚至不存储扩展名。我将创建一个控制表,存储指向文件的服务器,驱动器,路径等的指针。这样,您可以将这些图像移动到另一个框,仍然可以找到它们。 您是否需要对图片进行关键字标记?   如果是这样,那么您可能希望构建允许这种标记的适当表。

在我回复时,您/其他人可能已经解决了这些想法。希望这会有所帮助..


4
2017-12-17 18:24



1.all文件将被唯一命名2.系统将首先增长和增长它将获得1mil图像,然后以每月数万的速度增长。 3.将来会在某些时候对文件进行某种标记,这就是我想在数据库中存储某种标识数据的原因。 - s.mihai


我参与了一个项目,该项目在一年内存储了840万张图像,用于记录各种设备的状态。更频繁地访问更新的图像,并且除非发现促使某人挖掘档案的条件,否则很少寻找较旧的图像。

基于这种用法,我的解决方案是逐步将图像压缩成压缩文件。图像是JPG,每个大约20kB并且压缩不多,因此ZIP压缩方案是无。这样做只是为了将它们连接成一个文件系统条目,这在速度方面非常有助于NTFS从驱动器移动到驱动器,或查看文件列表。

超过一天的图像被组合成“每日”拉链;超过一个月的拉链被合并到各自的“月度”拉链中;最后不再需要一年以上的任何东西,因此被删除。

该系统运行良好,因为用户可以浏览文件(通过操作系统或许多客户端应用程序),并且所有内容都根据设备名称和时间戳命名。通常,用户知道这两条信息并且可以快速定位数百万图像中的任何一个。

我知道这可能与你的具体细节无关,但我想我会分享。


3
2017-12-17 17:02