Java:关于处理大量数据的建议.(第二部分)



>好吧。 所以我有大量的二进制数据(比如说,10GB)分布在一堆不同长度的文件(比如说 5000 个)上。

我正在编写一个 Java 应用程序来处理这些数据,我希望为数据访问建立一个良好的设计。 通常会发生什么是这样的:

  • 无论如何,所有数据都将在处理过程中被读取。
  • 每个文件(通常)按顺序读取,一次只需要几千字节。 但是,通常需要同时拥有每个文件的前几千字节,或者同时拥有每个文件的中间几千字节,等等。
  • 有时,应用程序希望在这里和那里随机访问一两个字节。

目前,我正在使用RandomAccessFile类来读取字节缓冲区(和ByteBuffers)。 我的最终目标是将数据访问封装到某个类中,以便它很快,我再也不用担心它了。 基本功能是,我将要求它从指定的文件中读取数据帧,并且鉴于上述注意事项,我希望最大程度地减少I/O操作。

典型访问示例:

  • 给我所有文件的前 10 KB!
  • 给我文件 F 的字节 0 到 999,然后给我字节 1 到 1000,然后给我 2 到 1001,等等,等等,...
  • 给我从文件 F 开始的某字节数据,从某某字节开始!

对一个好的设计有什么建议吗?

使用 Java NIO 和 MappedByteBuffers,并将文件视为字节数组列表。然后,让操作系统担心缓存、读取、刷新等细节。

@Will

相当不错的结果。 读取大型二进制文件快速比较:

  • 测试 1 - 使用 RandomAccessFile 进行基本顺序读取。2656 毫秒

  • 测试 2 - 带缓冲的基本顺序读取。47 毫秒

  • 测试 3 - 使用 MappedByteBuffers 进行基本顺序读取和进一步的帧缓冲优化。16 毫秒

哇。 您基本上是从头开始实现数据库。 是否有可能将数据导入实际的RDBMS并仅使用SQL?

如果您自己做,您最终将希望实现某种缓存机制,因此您需要的数据来自RAM(如果有的话),并且您正在较低层中读取和写入文件。

当然,这也需要许多复杂的事务逻辑来确保您的数据保持一致。

我建议你跟进 Eric 的数据库思想,了解数据库如何管理它们的缓冲区——有效地实现自己的虚拟内存管理。

但随着我进一步思考,我得出结论,大多数操作系统在实现文件系统缓存方面已经比没有 Java 中的低级访问更好。

不过,您可以从数据库缓冲区管理中吸取一个教训。数据库使用对查询计划的理解来优化管理策略。

在关系数据库中,通常最好从缓存中逐出最近使用的块。例如,在联接中保存子记录的"年轻"块将不会再次查看,而包含其父记录的块仍在使用中,即使它是"较旧的"。

另一方面,操作系统文件缓存经过优化,可以重用最近使用的数据(并在最近使用的数据之前读取)。如果您的应用程序不符合该模式,则可能值得自己管理缓存。

你可能想看看一个名为jdbm的开源,简单的对象数据库 - 它开发了很多这样的东西,包括ACID功能。

我已经为该项目做出了许多贡献,如果没有别的,值得对源代码进行审查,以了解我们如何解决您可能正在处理的许多相同问题。

现在,如果你的数据文件

不受你的控制(即你正在解析别人生成的文本文件,等等),那么jdbm使用的页面结构存储类型可能不适合你 - 但如果所有这些文件都是你正在创建和使用的文件,它可能值得一看。

@Eric

但是我的查询将比我用SQL做的任何事情都简单得多。 数据库访问不是比二进制数据读取贵得多吗?

这是为了回答有关最小化 I/O 流量的部分。在Java方面,你真正能做的就是把你的读卡器包装在BufferedReaders中。除此之外,您的操作系统将处理其他优化,例如将最近读取的数据保留在页面缓存中以及对文件进行预读以加快顺序读取。在 Java 中进行额外的缓冲是没有意义的(尽管您仍然需要一个字节缓冲区将数据返回到客户端)。

几天有人向我推荐了hadoop(http://hadoop.apache.org)。 看起来它可能相当不错,并且可能会有一些市场牵引力。

我会退后一步,问问自己为什么使用文件作为记录系统,以及与使用数据库相比有什么好处。数据库当然使您能够构建数据。鉴于SQL标准,从长远来看,它可能更易于维护。

另一方面,在数据库的约束下,您的文件数据可能不那么容易结构化。世界上最大的搜索公司:)不使用数据库进行业务处理。看这里和这里。

相关内容

  • 没有找到相关文章

最新更新