2017-08-21 33 views
1

我一直在试图查询包含多于1500000项的BaseX数据库。 当我运行此查询BaseX - 在XQuery中使用封闭xml时内存不足

for $item in collection('coll')//item 
    return $item (: returns an xml element :) 

它执行在不到一秒钟。

但是当我尝试在xml中返回结果时,出现“Out of main memory”错误。

<xml>{ 
    for $item in collection('coll')//item 
     return $item 
}</xml> 

这是一件让我想放弃了原生XML数据库的方法(同样的情况,与其他的DB,如eXistDB),因此,如果任何人有任何信息这一问题,这将是非常有益的。

感谢

回答

2

由于XQuery的语义,所有子节点需要,如果他们被新的父节点包裹被复制。这通过以下查询来演示,该查询比较原始节点和复制节点的节点标识。这将产生false

let $node := <node/> 
let $parent := <parent>{ $node }</parent> 
return $parent/node is $node 

由于复制几百万个节点是昂贵的,这不可避免地会导致内存外的一个错误。

如果结果写入文件,这里是一个务实的解决方案来解决这个限制:

(:~ 
: Writes element to a file, wrapped by a root node. 
: @param $path  path to file 
: @param $elements elements to write 
: @param $name  name of root node 
:) 
declare function local:write-to(
    $path  as xs:string, 
    $elements as element()*, 
    $name  as xs:string 
) as empty-sequence() { 
    file:write-text($path, '<' || $name || '>'), 
    file:append($path, $elements), 
    file:append-text($path, '</' || $name || '>') 
}; 

local:write-to('result.xml', <result/>, 'root') 

为了预测批评:这是一个明确的黑客。例如,该方法与BaseX的各种非默认序列化参数相冲突(如果需要输出XML声明,则结果不会很好)。

+0

从来没有想过,在这种情况下复制节点...这就解释了它。我会尝试你的建议并回复评论。非常感谢你! – unicorn

0

使用BaseX 9.0,您将能够通过COPYNODE选项临时禁用节点复制。您的查询将如下所示:

(# db:copynode false #) { 
<xml>{ 
    for $item in collection('coll')//item 
    return $item 
}</xml>