这里有一个更有效的XQuery可以删除吗?

时间:2019-02-10 22:35:18

标签: xml xquery exist-db

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

此处的相关信息是:

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

所以我有2000个XML,每个都有这样的东西:

def validate_color(base_colors, color):
    """
    Validate a color.
    """
    return color.split()[-1] in base_colors


if validate_color(base_colors, color):
    ...

现在我正尝试编写xQuery,因为我需要撤消某种语言。这意味着我实际上需要在2000个文件中删除每个定义了名称的文件。

是这样的:

<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 ...

但是这是永远的,实际上需要大量的内存。当然,在查看时……$ langs将是2000 * 400 = 800,000个项目。

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

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

但是,删除查询是否仍然如此低效,以至于本质上它无法执行800,000个项目,还是还有其他写方法?

更新我

所以我做了些改动,只是看一下。

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

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

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

1-30000 = 24秒

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

2 个答案:

答案 0 :(得分:1)

您需要对查询进行分析以确定确切的时间在哪儿花费最多,但是使用text()可能会缩短引擎使用范围索引的能力,因此会加载所有这些内容文档存入内存。

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

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

一次提交如此大的更新还可能导致数据库中存在额外的开销。如果不重要的一点是自动删除,则可以通过分批更新来提高性能。

答案 1 :(得分:0)

已经有一段时间了,因为我不得不进行批量删除。但是至少在eXist 2.2版中我可以做到:

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

没有必要遍历它们。

另外,在发出这种大规模删除操作之前,我将进行完整备份,以确保一切正常。

希望这会有所帮助。