【问题标题】:What is the fastest way to read, sort and merge multiple files in Java?在 Java 中读取、排序和合并多个文件的最快方法是什么?
【发布时间】:2012-09-04 05:17:02
【问题描述】:

我正在从事一个项目,该项目涉及读取和处理包含某些个人的各种数据的巨大 .txt 文件。

多个文件将按单个 ID(存在于所有文件中)读取和排序,然后合并,即从分配给同一 ID 的所有文件中检索所有条目。换句话说,每个人在每个文件中都可以有多个条目(即行)。我需要检索我找到的关于一个 ID 的所有信息,将其存储起来,然后传递给下一个。

到目前为止,我已经尝试过 FileChannelFileInputStreamMappedFileBuffer,但显然最适合我的情况是 FileInputStreamBufferedReader,为了比较它们,我发现推荐使用 Collection.sort() .一个重要的问题是我不知道要使用该应用程序的 PC 的性能,并且文件可能大于 2GB。任何帮助将不胜感激。

【问题讨论】:

  • 对数据库有限制吗?
  • 每个 ID 的预期行数和所有文件的 ID 总数是多少
  • @KARASZIIstván 对数据库没有限制,但文件的处理是在中间步骤中完成的(在每个步骤中,可能需要新的排序,具体取决于要遵循的工作流程和中间输入对于应用程序中的其他模块)。我想把它全部用 Java 编码,而不插入任何 SQL 语句或类似的东西,因为该应用程序稍后将只传递给 Java 开发人员......所以这几乎是一个请求
  • @每个 ID 的预期行数在所有文件中不会超过 500,并且 ID 的数量超过 2 - 300 万。

标签: java performance sorting io large-data


【解决方案1】:

如果您希望处理的数据多于目标环境的内存容量,那么您将不得不使用某种形式的磁盘流式传输或多次重新解析文件。

选择哪个选项取决于数据的分布。

如果每个 id 的行数相对较少(即很多不同的 id),那么假设您需要所有 id 的整理结果,那么重新解析将是最慢的。

如果 id 相对较少(即很多行),那么重新解析可能会变得更有效。

我的猜测是,在一般情况下,对每个 id 进行重新解析效率低下(但如果您知道可能有

然后的想法是,您只需解析文件一次,将结果放入一种列表映射中......

Map<Id,List<Record>>

你面临的问题是你没有足够的内存来保存这样的地图......

因此,您需要在磁盘存储上创建一个中间临时临时文件来保存每个 id 的列表。

磁盘存储有两种选择:

  1. 自己动手

  2. 使用数据库(例如 derby 或 hsqldb 或 ...)

选项 1 工作量更大,但您可以针对您的用例进行优化(即仅通过追加写入,然后在最后读回所有记录并对其进行排序)

选项 2 将更容易和更快地实施,但会降低性能,因为数据库将在 id 上维护索引,以防您希望在解析时随机读取数据(在此用例中您不会这样做) ...

如果我必须选择,我会从选项 2 开始,并且只会在性能欠佳的情况下给自己引入维护问题,即选项 1 将是。 (避免过早优化)

您将需要使用缓冲读取器(具有非常大 (64k) 的缓冲区,以避免通过竞争性读/写操作破坏磁盘(磁盘会影响性能)

【讨论】:

  • 如果您使用基于 java 的 db,例如 derby 或 hsqldb,则仅满足 java 的要求
  • 我在重新解析文件时也有同样的想法,但我没有足够的每个 ID 条目来提高效率。可用内存是一个问题,这就是尝试使用 MappedFile 缓冲区的原因,因为我可以将必要的空间保留为虚拟内存并将其传递给堆。这个想法是我还想避免在磁盘上写入,因为切换内核上下文以进行写入将非常耗时。
  • 我会尝试看看我用 derby 或 hsqldb 得到了什么
【解决方案2】:

如果文件足够大,您将不得不使用外部排序,在这种情况下,数据库真正开始成为最实用的选择。 JDK 中没有外部排序方法。

【讨论】:

  • 是的,我知道,我也可以使用数据库来完成,但规范仅使用 Java:/ 问题是我想在不包含的文件中逐行执行ID 重复并检索我从其他文件中获得的有关当前 ID 的所有信息。如果 .indexOf() 方法足够快,也许我什至不需要对它们进行排序。
  • 为什么不使用H2 In memory database 之类的东西?如果需要,它可以将表假脱机到本地存储,从而绕过任何内存限制。不过,性能可能会受到影响。
  • @Erik 感谢您的建议,我将尝试与 derby 进行比较,看看性能受到多大影响。
猜你喜欢
  • 2013-08-11
  • 2021-12-23
  • 1970-01-01
  • 2013-10-24
  • 2016-08-11
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 2011-10-26
相关资源
最近更新 更多