从大型xml文件中提取大型xml块的最佳方法

问题描述:

我使用XPath从XML文件中提取大型块。我的XML文件很大,它们来自PubMed。我的文件类型的一个例子是:从大型xml文件中提取大型xml块的最佳方法

ftp://ftp.ncbi.nlm.nih.gov/pubmed/baseline/medline17n0001.xml.gz

因此,通过使用

Node result = (Node)xPath.evaluate("PubmedArticleSet/PubmedArticle[MedlineCitation/PMID = "+PMIDtoSearch+"]", doc, XPathConstants.NODE); 

我得到PMIDtoSearch的文章,所以它的完美。但这需要很多时间。我必须做大约800,000次,所以这个解决方案需要两个多月的时间。有些块有超过400行,每个xml文件有超过4百万行。

我也尝试过这样的解决方案getElementsByTagName函数,但它几乎需要相同的时间。

您是否知道如何改进解决方案?

谢谢。

+0

VTD-XML是这个最终的XML解析器我将很快作出贡献的一段代码给你。 –

+0

我会编写XQuery来抓取GZIP,解压缩并存储到存在数据库中。然后针对该存储文档编写Xquery。 –

我把你的文件,并加载到存在-DB然后执行查询,基本上是这样的:

xquery version "3.0"; 
let $medline := '/db/Medline/Data' 
let $doc := 'medline17n0001.xml' 
let $PMID := request:get-parameter("PMID", "") 
let $article := doc(concat($medline,'/',$doc))/PubmedArticleSet/PubmedArticle[MedlineCitation/PMID=$PMID] 
return 
$article 

该文件从远程服务器返回的400毫秒。如果我加强了这个服务器,我希望少于这个,它可以处理多个并发请求。或者,如果你拥有本地更快的一切。

自己试试吧,我留在测试服务器上的数据(请记住,这是远程查询到在加州亚马逊微型服务器):

http://54.241.15.166/get-article2.xq?PMID=8

http://54.241.15.166/get-article2.xq?PMID=6

http://54.241.15.166/get-article2.xq?PMID=1

当然,整个文档都在那里。您可以将该查询更改为PMID = 667或999或其他任何值,然后将目标文档片段返回。

这是执行xpath查询的代码..在我的笔记本电脑上,结果看起来很不错..花了约1秒,不管pmid值多少。你打算如何提取文本。我可以更新代码以达到目标。

public static void main(String[] args) throws VTDException{ 
     VTDGen vg = new VTDGen(); 
     if (!vg.parseFile("d:\\xml\\medline17n0001.xml", false)) 
      return; 
     VTDNav vn = vg.getNav(); 
     AutoPilot ap = new AutoPilot(vn); 
     System.out.println("nesting level"+vn.getNestingLevel()); 
     String PMIDtoSearch = "30000"; 
     ap.selectXPath("/PubmedArticleSet/PubmedArticle[MedlineCitation/PMID = "+PMIDtoSearch+"]"); 
     System.out.println("====>"+ap.getExprString()); 
     int i=0,count=0; 
     System.out.println(" token count ====> "+ vn.getTokenCount()); 
     while((i=ap.evalXPath())!=-1){ 
      count++; 
      System.out.println("string ====>"+vn.toString(i)); 
     } 
     System.out.println(" count ===> "+count); 
    } 

正如@凯文布朗所言,数据库可能是正确的答案。但是,如果这是一次性过程,那么可能存在的解决方案比您的解决方案快得多,但不需要学习如何设置XML数据库的复杂性。

在您使用的方法中,存在两个主要成本:解析XML文档以在内存中创建树,然后搜索内存中文档以查找特定ID值。我猜测解析成本可能比搜索成本高一个数量级。

所以有两种成分,以获得良好的性能这一点:

  • 首先,你需要确保你只解析每个源文件一次(而不是每一次查询)。你还没有告诉我们足以让我能够分辨你是否已经这样做。第二,如果您要从单个文档中检索许多数据块,则需要在不对每个文档执行串行搜索的情况下执行此操作。实现此目的的最佳方法是使用查询处理器来构建索引以优化查询(如Saxon-EE)。或者,您可以“手动”构建索引,例如使用XQuery 3.1映射或使用XSLT中的xsl:key功能。

+0

它是一个很好的观点。那些我熟悉的数据集。它大约有21,000 MB的数据。如果是一次处理它,也许。然后再次,我可以作弊,因为我有一个伟大的亚马逊服务器映像,具有存储数据库和更多的加载,我可以在5分钟内启动。 –