平面文件数据库占有一席之地,并且非常适用于正确的域。
过去的邮件服务器和 NNTP 服务器确实将这些东西的实际应用范围推到了极限(实际上已经很远了——文件系统可以拥有数百万个文件和目录)。
平面文件数据库的两个最大弱点是索引和原子更新,但如果域合适,这些可能不是问题。
但您可以,例如,通过适当的锁定,使用基本文件系统命令进行“原子”索引更新,至少在 Unix 上是这样。
一个简单的例子是让索引过程在数据中运行以在临时名称下创建新的索引文件。然后,完成后,您只需重命名(系统调用 rename(2) 或 shell mv 命令)旧文件覆盖新文件。 Rename 和 mv 是 Unix 系统上的原子操作(即它要么工作要么不工作,并且永远不会缺少“中间状态”)。
与创建新条目相同。基本上将文件完全写入临时文件,然后将其重命名或 mv 到其最终位置。那么你在“数据库”中永远不会有一个“中间”文件。否则,您可能会遇到竞争条件(例如读取仍在写入的文件的进程,并且可能会在写入过程完成之前结束——丑陋的竞争条件)。
如果您的主索引与目录名称配合得很好,那么就可以了。例如,您可以使用散列方案创建目录和子目录来定位新文件。
使用文件名和目录结构查找文件非常快,因为当今大多数文件系统都会索引它们的目录。
如果您将一百万个文件放在一个目录中,那么您可能需要查看一些调整问题,但大多数情况下都可以轻松处理数十万个文件。请记住,如果您需要扫描目录,将会有很多文件需要扫描。通过目录进行分区有助于防止这种情况发生。
但这一切都取决于您的索引和搜索技术。
实际上,提供静态内容的现成网络服务器是一个大型的平面文件数据库,并且模型运行良好。
最后,当然,您可以使用大量免费的 Unix 文件系统级工具,但它们都存在与数以千计的文件有关的问题(将 grep 分叉 1000000 次以在文件中查找内容会产生性能折衷——开销只是加起来)。
如果您的所有文件都在同一个文件系统上,那么硬链接也为您提供了将同一个文件放在不同位置(主要用于索引)方面的选项(因为它们也是原子的)。
例如,您可以有一个“today”目录、一个“yesterday”目录、一个“java”目录和实际的消息目录。
因此,可以将帖子链接到“today”目录、“java”目录(例如,因为帖子被标记为“java”)和最终位置(例如 /articles/2008/12/ 01/my_java_post.txt)。然后,在午夜,您运行两个进程。第一个获取“今天”目录中的所有文件,检查它们的创建日期以确保它们不是“今天”(因为该过程可能需要几秒钟并且可能会潜入一个新文件),并将这些文件重命名为“昨天”。接下来,您对“昨天”目录执行相同的操作,只是在这里您只需在它们过期时将其删除。
同时,该文件仍在“java”和“.../12/01”目录中。由于您使用的是 Unix 文件系统和硬链接,因此“文件”只存在一次,这些都只是指向文件的指针。它们都不是“那个”文件,它们都是一样的。
您可以看到,虽然每个单独的文件移动都是原子的,但批量不是。例如,当“今天”脚本正在运行时,“昨天”目录可以很好地包含“昨天”和“前一天”的文件,因为“昨天”脚本尚未运行。
在事务型数据库中,您可以一次性完成所有操作。
但是,简单地说,这是一种久经考验的真实方法。尤其是 Unix,可以很好地使用该习惯用法,并且现代文件系统也可以很好地支持它。