【问题标题】:XQuery Java Performance with Large XML file大型 XML 文件的 XQuery Java 性能
【发布时间】:2012-06-06 02:15:42
【问题描述】:

我正在编写一些 Xquery 代码(使用 SAXON)来针对大型 XML 文件执行简单的 XQuery 文件。

XML 文件(位于 this.referenceDataPath)有 300 万个“行”节点,格式如下:

<row>
<ISRC_NUMBER>1234567890</ISRC_NUMBER>
</row>
<row>
<ISRC_NUMBER>1234567891</ISRC_NUMBER>
</row>
<row>
<ISRC_NUMBER>1234567892</ISRC_NUMBER>
</row>

等等……

XQuery 文档(位于 this.xqueryPath)是:

declare variable $isrc as xs:string external;
declare variable $refDocument external;
let $isrcNode:=$refDocument//row[ISRC_NUMBER=$isrc]
return count($isrcNode)

Java 代码是:

private XQItem referenceDataItem;
private XQPreparedExpression xPrepExec;
private XQConnection conn;

//set connection string and xquery file
this.conn = new SaxonXQDataSource().getConnection();
InputStream queryFromFile = new FileInputStream(this.xqueryPath);

//Set the prepared expression 
InputStream is  = new FileInputStream(this.referenceDataPath);
this.referenceDataItem = conn.createItemFromDocument(is, null, null);
this.xPrepExec = conn.prepareExpression(queryFromFile);
xPrepExec.bindItem(new QName("refDocument"), this.referenceDataItem);   

//the code below is in a seperate method and called multiple times
public int getCount(String searchVal){

    xPrepExec.bindString(new QName("isrc"), searchVal, conn.createAtomicType   (XQItemType.XQBASETYPE_STRING));

    XQSequence resultsFromFile = xPrepExec.executeQuery();
    int count = Integer.parseInt(resultsFromFile.getSequenceAsString(new Properties()));
    return count;

}

方法getCount被连续调用多次(例如1000000次)来验证XML文件中是否存在多个值。

Xquery 查询的当前速度是每次调用 getCount 大约 500 毫秒,考虑到 XML 文档在内存中并且查询是准备好的,这似乎非常慢。

我使用 XQuery 的原因是作为未来工作的概念证明,其中 XML 文件将具有更复杂的布局。

我在具有 8GB RAM 的 i7 上运行代码,因此内存不是问题 - 我还增加了为程序分配的堆大小。

关于如何提高这段代码的速度有什么建议吗?

谢谢!

【问题讨论】:

    标签: java xquery saxon


    【解决方案1】:

    对于如何提高速度的问题,最明显的答案是尝试 Saxon-EE,它有更强大的优化器,并且还使用字节码生成。我没有尝试过,但我认为 Saxon-EE 会检测到该查询将受益于构建索引,并且每次出现查询都会重复使用相同的索引。

    我要提出的另一个建议是声明变量 $refDocument 的类型 - 类型信息有助于优化器做出更明智的决策。例如,如果优化器知道 $refDocument 是单个节点,那么它就知道 $refDocument//X 将自动按文档顺序排列,而不需要任何排序操作。

    用“eq”代替“=”操作符也值得一试。

    【讨论】:

      【解决方案2】:

      Zorba 具有解析和查询大型 XML 文档的功能。 http://www.zorba-xquery.com/html/entry/2012/05/31/XML_Streaming

      提供了有关它的一些文档

      例如,在下面的代码 sn-p 中,我们通过 HTTP 解析一个 700MB 的文档,整个过程从上到下以流的方式发生:

      import module namespace http = "http://expath.org/ns/http-client";
      import module namespace p = "http://www.zorba-xquery.com/modules/xml";
      import schema namespace opt = "http://www.zorba-xquery.com/modules/xml-options";
      
      let $raw-data as xs:string := http:send-request(<http:request href="http://cf.zorba-xquery.com.s3.amazonaws.com/forecasts.xml" method="GET" override-media-type="text/plain" />)[2]
      let $data := p:parse($raw-data, <opt:options><opt:parse-external-parsed-entity opt:skip-root-nodes="1"/></opt:options>)
      return
          subsequence($data, 1, 2) 
      

      您可以在http://www.zorba-xquery.com/html/demo#CGPfEyXKvDwDfgzek/VTOIAIrJ8= 现场试用此示例

      【讨论】:

      • 谢谢!是否有适用于 Zorba 的 Java API 可以从本地文件而不是通过 HTTP 流式传输 XML 文件?
      • Zorba 有一个 Java API,但您可以直接从 XQuery 解析本地文件。我们是为 wikibooks 数据集做的,见 zorba-xquery.com/html/entry/2012/05/31/XML_Streaming
      • 目前尚不清楚为什么流式传输对于这个用例来说应该是一个优势,其中许多查询是针对可以保存在内存中的单个文档运行的。
      • 最后我决定改用内存数据库——性能要好得多。
      猜你喜欢
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 2018-12-04
      相关资源
      最近更新 更多