Java:有关处理大数据量的建议。 (半双)

时间:2020-03-06 14:47:23  来源:igfitidea点击:

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

我正在编写一个Java应用程序来处理这些数据,并且希望为数据访问建立一个良好的设计。通常情况将是这样的:

  • 一种或者另一种方式是,在处理过程中将读取所有数据。
  • 每个文件(通常)是按顺序读取的,一次只需要几千字节。但是,通常有必要同时拥有每个文件的前几千字节或者同时拥有每个文件的中几千字节,依此类推。
  • 有时,应用程序希望在此处和此处随机访问一两个字节。

目前,我正在使用RandomAccessFile类读取字节缓冲区(和ByteBuffers)。我的最终目标是将数据访问封装到某个类中,以使其速度很快,而我不必再为它担心。基本功能是,我将要求它从指定的文件中读取数据帧,并且鉴于上述考虑,我希望将I / O操作减至最少。

典型访问示例:

  • 给我所有文件的前10 KB!
  • 给我文件F的字节0到999,然后给我字节1到1000,然后给我2到1001,依此类推,等等,...
  • 给我一个从文件F开始的兆字节数据,从这个字节开始!

有什么好的设计建议吗?

解决方案

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

如果我们自己执行此操作,则最终将需要实现某种缓存机制,因此,如果需要的数据从RAM中出来,则它们将在较低的层中读写文件。

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

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

埃里克

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

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

我建议我们跟进Eric的数据库概念,并了解数据库如何有效地管理其缓冲区,以实现其自身的虚拟内存管理。

但是,当我考虑得更多时,我得出的结论是,大多数操作系统在实现文件系统缓存方面已经比在没有Java低级访问的情况下做得更好。

但是,我们可能会考虑数据库缓冲区管理中的一课。数据库使用对查询计划的理解来优化管理策略。

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

另一方面,对操作系统文件缓存进行了优化,以重用最近使用的数据(并在最近使用的数据之前进行读取)。如果应用程序不适合该模式,则值得我们自己管理缓存。

@将要

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

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

我们可能想看看一个名为jdbm的开放源代码,简单的对象数据库,它开发了很多这类东西,包括ACID功能。

我已经对该项目做出了许多贡献,如果没有其他事情可以看到我们如何解决我们可能正在解决的许多相同问题,那么值得对源代码进行回顾。

现在,如果数据文件不受控制(例如,我们正在解析其他人生成的文本文件等),那么jdbm使用的页面结构存储类型可能不适合我们,但是如果所有这些文件是我们正在创建和使用的文件,可能值得一看。

前几天,我有个人向我推荐hadoop(http://hadoop.apache.org)。看起来可能非常不错,并且可能会吸引一些市场。

我会退后一步,问自己为什么将文件用作记录系统,以及从数据库中获得的收益是什么。数据库无疑使我们能够构建数据。给定SQL标准,从长远来看,它可能更具可维护性。

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