这里有没有更高效的XQuery删除?

Is there a more efficient XQuery here for deletion?

我有一个大型 eXist-db 数据库,我正在其中实现一些功能来管理内部数据。

这里的相关信息是:

有 2000 位客户。
每个客户可以访问 400 个文档。
现在每个文档都有 20 种语言。

所以我有 2000 个 XML,每个都有这样的内容:

<customer name="foo">
    <document num="A01" subscribed="Y">
      <languages>
        <lang subscribed="N">Arabic</lang>
        <lang subscribed="Y">Polish</lang>
... and so on for 400 documents for 20 languages ...

现在我尝试编写一个 xQuery,因为我需要撤销一种语言。这意味着我需要从本质上删除 2000 个文件,对于每个文档,定义了名称的

所以像这样:

 for $langs in $g:collection.customers//lang[text()=$deletelang]
 return update delete $langs

但这需要很长时间,而且实际上需要大量内存。当然在查看它时...$langs 将是 2000*400 = 800,000 个项目。

我会注意到存在一个范围索引,其中包含:

<create qname="lang" type="xs:string" nested="no"/>

但是,删除查询是否效率太低,以至于基本上无法执行 800,000 个项目,还是应该编写其他方式?

更新我

所以我稍微改变了一下,只是为了看看。

1)根据评论,我改为“。”来自文本()

2) 我在其周围添加了 subsequence() 以测试各种尺寸>>

for $langs in subsequence($g:collection.customers//lang[.=$deletelang],1,30000)

1-30000 = 24s

所以 运行 整个集合现在 = 110s

您需要分析查询以确定它花费最多时间的确切位置,但您对 text() 的使用可能会使引擎使用范围索引的能力短路,因此正在加载所有这些文件都存入内存。

text()选择文本节点,一个元素中可能有多个文本节点。即:element lang { text { 'Pol' }, text { 'ish' } } 将产生一个看起来像 <lang>Polish</lang> 但有两个文本节点的元素,并且会在假设只有一个的谓词上失败:[text() = 'Polish']

尝试在谓词中使用点:[. = $deletelang]

一次提交如此大的更新也可能在数据库中有额外的开销。如果以原子方式完成删除并不重要,您可以通过批处理更新来提高性能。

我已经有一段时间没有进行大规模删除了。但至少在 eXist 2.2 版中我可以做到:

let $langs := $g:collection.customers//lang[.=$deletelang]
return update delete $langs

没有必要遍历它们。

另外,我会在发布此类大规模删除之前进行完整备份,以确保一切正常。

希望对您有所帮助。