有关处理大量数据的建议

所以我有一个“大”的数字数据的“非常大”的ASCII文件(一共几千兆字节),我的程序需要至少按顺序处理整个数据。

有关存储/加载数据的建议吗? 我曾想过将文件转换为二进制文件以使它们更小并加快加载速度。

我应该一次性将所有内容加载到内存中吗?
如果没有,是否打开了部分加载数据的好方法?
什么是与Java相关的效率提示?

那么如果处理需要在多个文件和多个缓冲区的数据中跳转呢? 二进制文件的不断打开和关闭会变得昂贵吗?

我是‘内存映射i / o’的忠实粉丝,又名‘直接字节缓冲区’ 。 在Java中,它们被称为Mapped Byte Buffers是java.nio的一部分。 (基本上,这种机制使用操作系统的虚拟内存分页系统来“映射”你的文件,并以编程方式将它们作为字节缓冲区提供。操作系统将自动神奇且非常快速地管理磁盘和内存中的字节。

我建议这种方法,因为a)它适用于我,和b)它将让你专注于你的算法,让JVM,操作系统和硬件处理性能优化。 他们经常知道什么是最好的,比我们低级程序员更好。 ;)

您将如何在您的上下文中使用MBB? 只需为每个文件创建一个MBB,然后根据需要阅读它们。 您只需要存储结果。 。

顺便说一句:你用多少数据来处理GB? 如果它超过3-4GB,那么在32位计算机上这将不适合您,因为MBB实现是平台架构在可寻址内存空间上的被告。 64位计算机和操作系统将带您到1TB或128TB的可映射数据。

如果您正在考虑性能,那么请了解Kirk Pepperdine(一位有点着名的Java性能大师。)他参与了一个网站www.JavaPerformanceTuning.com,它有更多的MBB细节: NIO性能提示和其他Java性能相关的东西。

您可能想要查看Wide Finder项目中的条目(谷歌搜索“广泛查找器”java )。

Wide finder涉及读取日志文件中的大量行,因此请查看Java实现,看看哪些有效,哪些无效。

您可以转换为二进制,但如果您需要保留原始数据,那么您有1+个数据副本。

在原始ascii数据之上构建某种索引可能是切实可行的,因此如果您需要再次查看数据,可以在以后的时间内更快地完成。

按顺序回答您的问题:

我应该一次性将所有内容加载到内存中吗?

如果没有,则不是。 对于某些文件,您可能会,但如果您只是按顺序处理,只需逐个进行某种缓冲读取,并在整个过程中存储您需要的任何内容。

如果没有,是否打开了部分加载数据的好方法?

BufferedReaders / etc是最简单的,尽管您可以更深入地了解FileChannel / etc以使用内存映射I / O一次浏览数据窗口。

什么是与Java相关的效率提示?

这真的取决于你对数据本身做了什么!

如果没有进一步了解正在进行什么样的处理,这里有一些关于我做类似工作时的一般性想法。

  1. 编写应用程序的原型(甚至可能是“扔掉一个”),对数据集执行一些任意操作。 看看它有多快。 如果您能想到的最简单,最天真的事情是可以接受的快速,不用担心!

  2. 如果天真的方法不起作用,请考虑预处理数据,以便后续运行将在可接受的时间内运行。 你提到必须在数据集中“跳转”很多。 有没有办法预处理出来? 或者,一个预处理步骤可以生成更多数据 – 索引数据 – 提供有关数据集的关键,必要部分的字节精确位置信息。 然后,您的主要处理运行可以利用此信息直接跳转到必要的数据。

总而言之,我的方法是立即尝试一些简单的事情,看看性能如何。 也许会没事的。 否则,请考虑以多个步骤处理数据,从而为不频繁的预处理节省了最昂贵的操作。

不要“将所有内容加载到内存中”。 只需执行文件访问,让操作系统的磁盘页面缓存决定何时直接从内存中取出内容。

这很大程度上取决于文件中的数据。 大型大型机一直在进行顺序数据处理,但它们通常不会对数据使用随机访问。 他们只是一次拉一行,然后继续处理。

对于随机访问,通常最好使用缓存包装器构建对象,这些包装器知道文件在何处需要构造的数据。 需要时,他们会读取数据并自行构建。 这样当内存紧张时你就可以开始杀掉一些东西,而不必过于担心以后无法取回它。

你真的没有给我们足够的信息来帮助你。 您是否需要完整地加载每个文件才能进行处理? 或者你可以逐行处理吗?

即使对于不是非常大的文件,一次加载整个文件也可能导致性能不佳。 最好的办法是定义一个适合您的缓冲区大小,一次读取/处理缓冲区数据。

我发现Informatica是一个非常有用的数据处理工具。 好消息是更新的版本甚至允许Java转换。 如果您正在处理数TB的数据,那么可能需要时间来寻找最佳的ETL工具。

我假设你想对这里的处理结果做点什么,比如把它存放在某个地方。

如果您的数值数据是定期采样的,并且您需要进行随机访问,请考虑将它们存储在四叉树中 。

我建议强烈利用正则表达式并查看“新”IO nio包以获得更快的输入。 那么它应该尽可能快地实现预期千兆字节的数据。

如果可能的话,将数据导入数据库。 然后,您可以利用所有可用的索引,缓存,内存固定和其他function。

如果需要多次访问数据,请将其加载到数据库中。 大多数数据库都有某种批量加载实用程序。 如果数据都可以适合内存,并且您不需要经常保留或访问它,您可以用Perl或您喜欢的脚本语言编写简单的东西。