2017-08-21 41 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>