在30GB XML数据集上搜索正则表达式模式。利用16GB的内存

时间:2008-09-21 21:04:07

标签: java xml

我目前有一个Java SAX解析器,它从30GB的XML文件中提取一些信息。

目前是:

  • 阅读每个XML节点
  • 将其存储到字符串对象中,
  • 在字符串上运行一些regexex
  • 将结果存储到数据库

数百万元素。我在16GB内存的计算机上运行它,但内存没有被充分利用。

是否有一种简单的方法可以从输入文件中动态“缓冲”大约10gb的数据?

我怀疑我可以手动接受一个'生产者''消费者'的多线程版本(在一侧加载对象,使用它们并在另一侧丢弃),但该死的,XML现在很古老,没有高效的库捣乱他们?

10 个答案:

答案 0 :(得分:4)

  1. 只是为了覆盖基础,Java是否能够使用你的16GB?您(显然)需要使用64位操作系统,并且需要使用-d64 -XMx10g运行Java(或者需要为其分配大量内存)。

  2. 内存极不可能是你正在做的事情的限制因素,所以你真的不应该看到它被充分利用。您应该是IO或CPU绑定。最有可能的是,它将是IO。如果是,IO,确保你正在缓冲你的溪流,然后你已经完成了很多工作;你唯一能做的就是购买更快的硬盘。

  3. 如果你确实受CPU限制,那么你可能会遇到正则表达式而不是XML解析的瓶颈。

    请参阅this(引用this

  4. 如果您的瓶颈在SAX,您可以尝试其他实施。我能想到以下几种选择:

    • StAX(有多个实现; Woodstox是最快的之一)
    • Javolution
    • 使用JFlex
    • 滚动您自己
    • 滚动您自己的专案,例如使用正则表达式

    对于最后两个,你的XML子集越受限制,你就越有效率。

  5. 很难说,但正如其他人所提到的,XML本机数据库可能是一个很好的选择。我对这些经验的经验有限,但我知道至少Berkeley DB XML支持基于XPath的索引。

答案 1 :(得分:2)

没有Java经验,抱歉,但也许您应该更改解析器? SAX应该按顺序工作,不需要缓冲大部分文件...

答案 2 :(得分:2)

SAX本质上是“事件驱动的”,所以你应该从元素到元素保持的唯一状态是与该元素相关的状态,而不是整个文档。你还在维护其他什么状态?为什么?当每个“完整”节点(或一组节点)到来时,您应该丢弃它们。

答案 3 :(得分:2)

首先,试着找出让你失望的原因。

  • 从内存中解析时解析器的速度有多快?
  • 使用大尺寸的BufferedInputStream会有帮助吗?

分割XML文件是否容易?一般情况下,通过30 GiB的任何类型的数据进行混洗都需要一些时间,因为您必须首先从硬盘驱动器加载它,因此您始终受限于此速度。你可以将负载分配给多台机器,也许可以使用类似Hadoop的东西吗?

答案 4 :(得分:1)

我真的不明白你要用大量的XML做什么,但我得到的印象是

  • 使用XML对于存储的数据是错误的
  • 你正在缓冲超出你应该做的事情(并且你通过这样做放弃了SAX解析的所有优点)。

除此之外:XML并不古老,并且在大规模和积极使用中。您认为所有这些互动网站用于互动元素的是什么?

答案 5 :(得分:1)

您是否因为对数据库进行多次小型提交而放慢速度?听起来你几乎总是从你的程序写入数据库,并确保你不经常提交可以提高性能。可能还准备你的陈述和其他标准批量处理技巧可能会有所帮助

除了这个早期评论之外,我们还需要更多信息 - 你是否有一个方便的分析器,可以找出让事情变得缓慢的原因

答案 6 :(得分:1)

您可以使用Jibx库,并将XML“节点”绑定到表示它们的对象。你甚至可以重载一个ArrayList,然后当添加x个对象时,一次执行所有正则表达式(大概是使用执行此逻辑的对象上的方法)然后将它们保存到数据库中,然后再允许“add”方法再次完成。

Jibx托管在SourceForge上:Jibx

详细说明:您可以将XML绑定为这些专用String持有者的“集合”。因为您将其定义为集合,所以必须选择要使用的集合类型。然后,您可以指定自己的ArrayList实现。

按如下方式覆盖add方法(忘记返回类型,例如假定为void):

public void add(Object o) {
    super.add(o);
    if(size() > YOUR_DEFINED_THRESHOLD) {
        flushObjects();
    }
}

YOUR_DEFINED_THRESHOLD

是要在arraylist中存储多少个对象,直到它必须刷新到数据库。 flushObjects();只是执行此逻辑的方法。该方法将阻止从XML文件添加对象,直到此过程完成。但是,这没关系,数据库的开销可能远远大于文件读取和解析。

答案 7 :(得分:0)

我建议先将大量的XML文件导入原生XML数据库(例如eXist,如果你正在寻找开源的东西,从不自己测试过),然后执行迭代分页查询,一次处理数据小块。

答案 8 :(得分:0)

你可能想尝试Stax而不是SAX,我听说这种事情更好(我自己没有用过)。

答案 9 :(得分:0)

如果XML中的数据是与订单无关的,您是否可以对进程进行多线程处理以拆分文件或从文件中的不同位置开始运行多个进程?如果你没有I / O限制,应该有助于加快速度。