10

我有一个流程,最初将生成 3-4 百万个 PDF 文件,并以 80K/天的速度继续。它们每个都非常小(50K),但我担心的是如何管理我生成的文件总量以便于查找。一些细节:

  1. 生成文件后,我将运行一些其他步骤,并且将有一些服务器参与,因此我需要在生成文件时注意它们。
  2. 生成后,这些文件将通过我编写的查找过程可用。本质上,我需要根据每个文件唯一的订单号来提取它们。
  3. 在任何时候,现有的订单号可能会被重新提交,并且生成的文件将需要覆盖原始副本。

最初,我计划将这些文件全部写入 NAS 上的单个目录,但我意识到这可能不是一个好主意,因为它们有数百万个,Windows 可能无法非常优雅地处理百万个文件查找。我正在寻找一些建议:

  1. 一个文件夹可以吗?这些文件永远不会被列出——它们只会使用 System.IO.File 和我已经确定的文件名来检索。
  2. 如果我创建一个文件夹,我是否可以使用 System.IO.DirectoryWatcher 监视新文件,即使有这么多文件,还是会因为有这么多文件而开始变得迟缓?
  3. 是否应该将它们作为 BLOB 存储在 SQL Server 数据库中?因为我需要通过参考值来检索它们,所以这可能更有意义。

谢谢你的想法!

4

12 回答 12

6

要回答您的问题:

  1. 我不会将它们存储在一个文件夹中。在某些时候,您可能会想要查看磁盘上的实际文件,而不是其他方式。
    相反,为什么不将它们存储在单独的目录中,分成 1000 个批次?可能使用 ID 作为密钥。
  2. 这么多文件可能会淹没 DirectorWatcher,所以有些文件会丢失。我过去用过这个,过了某个点(几百个),我发现它开始丢失文件。可能对传入文件使用不同的目录,然后每隔一段时间处理一次。然后,这可以触发更新原始文件的过程。
  3. 我不会将文档存储在数据库中,但肯定会将元数据存储在数据库中。
于 2009-08-10T21:59:37.857 回答
6

您可以轻松地将文件组织到多个文件夹中,而无需通过业务逻辑或每天订购来执行此操作,如果这种排序是“块状的”(一个文件夹中有很多点击,其他文件夹中点击很少),这尤其好。

最简单的方法是为文件名创建一个唯一的哈希,这样也许你会得到这样的东西:

sf394fgr90rtfofrpo98tx.pdf

然后把它分成两个字符的块,你会得到这个:

sf/39/4f/gr/90/rt/fo/fr/po/98/tx.pdf

如您所见,它为您提供了一个可以轻松导航的深层目录树。

使用良好的散列函数,这将非常均匀地分布,每个目录的条目永远不会超过 1296 个。如果您遇到冲突(这应该非常罕见),只需在末尾添加一个数字:tx.pdf、tx_1.pdf、tx_2.pdf。同样,如此大的散列上的冲突应该是非常罕见的,因此你得到的那种聚集不是问题。

你说这些文件是数字签名的,所以你可能在那里以签名字符串的形式拥有你需要的哈希值。

于 2009-08-10T22:53:40.587 回答
3

我会将文件分组到特定的子文件夹中,并尝试以某种业务逻辑方式组织它们(子文件夹)。也许在某一天制作的所有文件?在每天的六个小时内?或者每 # 个文件,我会说最多 1000 个。(那里可能有一个理想的数字,希望有人会发布它。)

文件是否会过期并被删除?如果是这样,排序和文件是可删除的块。如果不是,我可以成为您的硬件供应商吗?

将文件存储在数据库中的双方都有争论。

  • 一方面,您获得了增强的安全性,因为从数据库中提取文件更加尴尬;另一方面,您可能会获得更差的性能,因为从数据库中提取文件更加尴尬。
  • 在数据库中,您不必担心每个文件夹、扇区、NAS 集群有多少文件——这是数据库的问题,并且可能他们对此有很好的实现。另一方面,管理/审查数据会更加困难,因为它会在一个表中出现大量的 blob,而且,嗯,很糟糕。(您可以根据上述业务逻辑对表进行分区,这将使删除或归档无限容易执行。或者可能是分区视图,因为表分区有 1000 个分区的限制。)
  • SQL Server 2008 具有 FileStream 数据类型;不太了解,可能值得研究。

最后一点要担心的是保持数据“对齐”。如果数据库将信息与文件的路径/名称一起存储在文件上,并且文件被移动,您可能会完全被淹没。

于 2009-08-10T22:12:09.280 回答
2

1)这与我通常宣扬的完全相反,但您可能希望将它们存储在 SQL 数据库中,因为它们是真正的小文件。SQL Server 还允许您快速轻松地找到所需的文件,而不会出现通常与枚举如此大的目录相关的任何疯狂的磁盘垃圾。此外,将文件存储在 SQL 中(虽然我通常反对)将大大简化备份/恢复过程。

2)将它们全部存储在目录中,然后使用 windows 索引服务 ( shivers ) 对它们进行索引,或者在 SQL Server 中创建自己的索引,其中包含文件名和完整路径。我建议将它们存储在单独的目录中,每个目录只有几万个文件。也许您可以使用订单年份作为文件夹名称?

不管它们是如何存储的——不要扫描目录来查找文件——你肯定需要某种索引。

希望这可以帮助!

于 2009-08-10T22:07:47.777 回答
2

1) 一个简单的文件夹使用单独的索引可能很快就可以接受,但因为将它放在子目录中是微不足道的,这将使您能够浏览只是这样做。
所以现在你必须弄清楚你的命名约定。尽管我通常会建议使用哈希来获得 id 的均匀分布,但由于您做了这么多,使用您已经获得的值可能是有意义的。如果您有订单号,您是否也有时间戳?如果是这样,只需在订单号前加上时间戳即可。

请注意,如果您使用的是订单 ID,您可能会遇到http://en.wikipedia.org/wiki/Benford%27s_law

于 2009-08-10T22:35:55.270 回答
2

你需要测试它。所有这些解决方案都依赖于底层文件系统。有些文件系统可以处理巨大的目录,有些则不能。有些文件系统索引它们的目录,有些不索引(这两点不一定相关)。

将内容分解为目录树有合理的机会来提高性能,这仅仅是因为最终,各个目录往往具有很少的整体条目。这适用于大多数文件系统,因为即使是对文件进行线性目录搜索的“愚蠢”系统也可以相当快地搜索几百个条目。

如果文件系统正在索引目录(例如,btree,或者只是在内部对其进行排序,这在这种情况下实际上是同一件事),那么目录大小就不那么重要了,尽管有些工具可能会抱怨(加载 Windows 资源管理器窗口有4M文件,谁知道会发生什么)。

因此,我会研究您计划的操作系统和文件系统选项,并对其进行测试,看看哪个最适合您。

于 2009-08-10T23:10:21.940 回答
1

确定子目录的一些逻辑顺序并将它们存储在一个文件夹中不超过 512 个文件的块中。

不要将文件存储在数据库中。数据库用于数据,文件服务器用于文件。将它们存储在文件服务器上,但将路径和检索信息存储在数据库中。

于 2009-08-10T22:09:05.123 回答
1

为什么不考虑将所有这些文件转换为 PDF 后存储到数据库(blob)中,因此优点:

  1. 我相信您不必直接处理 OS I/O,并将一切交给数据库。
  2. 无需哈希命名
  3. 易于备份和维护
于 2009-08-10T23:27:14.090 回答
1

使用数据库存储文件时,尤其是小文件,开销应该很小。但您也可以执行以下操作:

DELETE FROM BLOBTABLE WHERE NAME LIKE '<whatever>'

或者当您有到期日期或想要刷新文件时,您可以通过以下方式将其删除:

DELETE FROM BLOBTABLE WHERE CREATIONDATE < ...
etc...
于 2011-08-24T17:37:59.413 回答
0

问题:

为什么这些文档需要生成并存储为 PDF?

如果可以生成它们,为什么不将数据保存在数据库中并在需要时动态生成它们呢?这意味着您可以搜索无论如何搜索所需的实际数据,而不会将文件放在磁盘上。这样您还可以在需要时更新 PDF 模板而无需重新生成任何内容?

于 2009-08-10T22:07:34.343 回答
0

我的文件数据库包含超过 400 万个文件夹,每个文件夹中有很多文件。

只是将所有文件夹扔到一个目录中。NTFS 可以毫无问题地处理这个问题,并且当您需要移动它时,robocopy 等高级工具可以提供帮助。

只要确保您可以在不扫描的情况下索引文件。我通过在 mysql 数据库中折腾我的索引来做到这一点。

所以为了得到一个文件,我在一些元数据上搜索 mysql 数据库并得到一个索引。然后我使用这个索引直接读取文件。到目前为止对我来说很好。但请注意,您会将所有内容都变成随机访问,因此是随机读/写。这对于 HDD 来说性能很差,但幸运的是 SSD 会有很大帮助。

另外,我不会将文件扔到 mysql 数据库中。如果没有了解 mysql 的客户端,您将无法进行网络读取。现在我可以使用任何程序通过网络访问任何文件,因为我可以使用它的网络 URL。

于 2009-08-10T22:13:28.140 回答
0

我认为就像许多其他人所说的那样,您应该创建子文件夹,但您可以通过代码找到数据。例如,如果 datetime 有效,请使用它。从阅读您所说的内容来看,报告(每日、每周、每日 X 报告、每小时 Y 报告等)似乎存在某种形式的层次结构,我将查看生成和构建报告的时间和原因的结构我的目录就是这样。

于 2009-08-11T11:31:27.287 回答