好的。所以我有大量的二进制数据(比方说,10GB)分布在不同长度的一堆文件(比方说5000)上。
我正在编写一个Java应用程序来处理这些数据,我希望为数据访问建立一个好的设计。通常情况会是这样的:
目前我使用RandomAccessFile类读取字节缓冲区(和ByteBuffers)。我的最终目标是将数据访问封装到某个类中,以便它快速,我再也不用担心它了。基本功能是我将要求它从指定文件中读取数据帧,并且我希望在上述考虑因素的情况下最小化I / O操作。
典型访问的示例:
对优秀设计的任何建议?
答案 0 :(得分:9)
使用Java NIO和MappedByteBuffers,并将您的文件视为字节数组列表。然后,让操作系统担心缓存,读取,刷新等细节。
答案 1 :(得分:2)
@Will
非常好的结果。读取大型二进制文件快速比较:
测试1 - 使用RandomAccessFile进行基本顺序读取。 2656 ms
测试2 - 使用缓冲进行基本顺序读取。 47 ms
测试3 - 使用MappedByteBuffers进行基本顺序读取以及进一步的帧缓冲优化。 16 ms
答案 2 :(得分:1)
哇。您基本上是从头开始实现数据库。是否有可能将数据导入实际的RDBMS并只使用SQL?
如果你自己这样做,你最终会想要实现某种缓存机制,所以你需要的数据来自RAM,如果它存在,你正在读取和编写较低层的文件。
当然,这也需要很多复杂的事务逻辑来确保您的数据保持一致。
答案 3 :(得分:1)
我建议您跟进Eric's database idea并了解数据库如何管理缓冲区 - 有效实施自己的虚拟内存管理。
但是当我考虑更多时,我得出的结论是,大多数操作系统在实现文件系统缓存方面已经比在没有Java的低级访问时可能做得更好。
但是,您可以考虑从数据库缓冲区管理中吸取一个教训。数据库使用对查询计划的理解来优化管理策略。
在关系数据库中,通常最好从缓存中逐出最近使用的块。例如,在连接中保存子记录的“年轻”块不会再次被查看,而包含其父记录的块仍然在使用,即使它是“较旧”。
另一方面,操作系统文件缓存经过优化,可重复使用最近使用的数据(并在最近使用的数据之前读取)。如果您的应用程序不适合该模式,则可能需要自行管理缓存。
答案 4 :(得分:1)
你可能想看一个名为jdbm的开源简单对象数据库 - 它开发了很多这样的东西,包括ACID功能。
我已经为该项目做了很多贡献,如果没有其他任何内容可以查看我们如何解决您可能正在处理的许多相同问题,那么值得对源代码进行审核。
现在,如果您的数据文件不在您的控制之下(即您正在解析由其他人生成的文本文件等),那么jdbm使用的页面结构类型的存储可能不适合您 - 但如果所有这些文件都是您正在创建和使用的文件,则可能值得一看。
答案 5 :(得分:0)
@Eric
但是我的查询将比使用SQL做的任何事情都简单得多。数据库访问不会比二进制数据读取更昂贵吗?
答案 6 :(得分:0)
这是为了回答有关最小化I / O流量的部分。在Java方面,您所能做的就是将读者包装在BufferedReaders中。除此之外,您的操作系统还将处理其他优化,例如将最近读取的数据保留在页面缓存中以及对文件进行预读以加速顺序读取。在Java中进行额外的缓冲是没有意义的(尽管你仍然需要一个字节缓冲区来将数据返回给客户端)。
答案 7 :(得分:0)
前几天我有人向我推荐了hadoop(http://hadoop.apache.org)。看起来它可能非常好,并且可能具有一定的市场吸引力。
答案 8 :(得分:0)