BaseX - 在 XQuery 中使用封闭 xml 时内存不足
BaseX - Out of memory when using enclosing xml in XQuery
我一直在尝试查询包含超过 1500000 个项目的 BaseX 数据库。
当我运行这个查询
for $item in collection('coll')//item
return $item (: returns an xml element :)
执行不到一秒。
但是当我尝试 return 结果时 xml 我得到一个 "Out of main memory" 错误。
<xml>{
for $item in collection('coll')//item
return $item
}</xml>
这让我想放弃原生 xml 数据库方法(其他数据库也会发生同样的情况,例如 eXistDB),所以如果有人知道这个问题的任何信息,那将非常有帮助。
谢谢
由于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声明,结果将是非良构的等)。
使用 BaseX 9.0,您可以通过 COPYNODE 选项暂时禁用节点复制:
(# db:copynode false #) {
<xml>{
for $item in collection('coll')//item
return $item
}</xml>
}
我一直在尝试查询包含超过 1500000 个项目的 BaseX 数据库。 当我运行这个查询
for $item in collection('coll')//item
return $item (: returns an xml element :)
执行不到一秒。
但是当我尝试 return 结果时 xml 我得到一个 "Out of main memory" 错误。
<xml>{
for $item in collection('coll')//item
return $item
}</xml>
这让我想放弃原生 xml 数据库方法(其他数据库也会发生同样的情况,例如 eXistDB),所以如果有人知道这个问题的任何信息,那将非常有帮助。
谢谢
由于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声明,结果将是非良构的等)。
使用 BaseX 9.0,您可以通过 COPYNODE 选项暂时禁用节点复制:
(# db:copynode false #) {
<xml>{
for $item in collection('coll')//item
return $item
}</xml>
}