代码之家  ›  专栏  ›  技术社区  ›  Kevin Brown

这里是否有更有效的XQuery用于删除?

  •  2
  • Kevin Brown  · 技术社区  · 6 年前

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

    相关信息如下:

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

    所以我有2000个XML,每个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个文件中定义了名称的每个文档的<lang>。

    所以像这样:

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

    但这要花很长时间,实际上需要大量的记忆。当然,看看它…$langs为2000*400=800000件。

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

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

    但是,删除查询的效率是如此之低,以至于基本上不能用800000个项目执行,还是有其他的方法需要编写?

    更新我

    所以我改变了一些东西来看看。

    1)根据评论,我从文本()改为“.”

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

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

    1-3000=24s

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

    2 回复  |  直到 6 年前
        1
  •  1
  •   wst    6 年前

    您需要对查询进行概要分析,以确定它在哪里花费的时间最多,但您可能使用 text() 使引擎无法使用范围索引,因此正在将所有这些文档加载到内存中。

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

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

    数据库中还可能存在额外的开销,以便一次提交如此大的更新。如果原子地删除并不重要,可以通过批处理更新来提高性能。

        2
  •  0
  •   westbaystars    6 年前

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

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

    不需要把它们都循环一遍。

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

    希望这有帮助。