【问题标题】:How to wait for a MarkLogic spawn function to complete如何等待 MarkLogic 生成函数完成
【发布时间】:2018-12-27 17:23:56
【问题描述】:

我有一个要求,我遍历 10,000,000 个文档,并且对于每个文档我执行一些操作并将一些值存储在“/count.xml”中。当我迭代到第二个文档时,我用更新的值更新“/count.xml”

目前这是我正在做的,这里 $total-records 是 10,000,000

let $total-records := xdmp:estimate(cts:search( //some code))
let $batch-size := 5000
let $pagination := 0
let $bs := 
   for $records in 1 to fn:ceiling($total-records  div $batch-size )
   let $start := fn:sum($pagination + 1)
   let $end := fn:sum($batch-size + $pagination)
   let $_ := xdmp:set($pagination, $end)
   return
    xdmp:spawn-function
    (
    function() {
     for $each in cts:search( //some code)[$start to $end]
     return //some operation and update '/count.xml' with some updated values
    },
    <options xmlns="xdmp:eval"><commit>auto</commit><update>true</update</options>
    )
let $doc := doc("/count.xml")
return ()

所以这里的问题是我需要在迭代所有文档之后读取“/count.xml”文件,但是上面的代码使用 spawn 任务

让 $doc := doc("/count.xml")

不会是最新的,因为上面的 spawn 任务将在不同的线程上运行。

我需要一个解决方案

让 $doc := doc("/count.xml")

等待所有生成任务完成。

我遇到过

<result>{fn:true()}</result>

选项也是如此,但我不知道它是否会起作用,因为变量

$bs

没有在任何地方使用,并且文档说“当调用请求在任何操作中使用值未来时,它将自动等待生成的任务完成并使用结果。”

还有其他选择吗

让 $doc := doc("/count.xml")

只有在所有生成任务完成后才会执行行

【问题讨论】:

    标签: xquery marklogic


    【解决方案1】:

    要处理 1000 万份文档,您可能需要生成类似 10000 批的 1000 份文档。我认为这在 MarkLogic 中不会很好。

    我建议您研究一下 MarkLogic 的内置聚合功能。参见例如cts:sum-aggregate。您可能能够预先计算每个文档的中间结果,您可以在运行时使用这些聚合功能进行聚合。那肯定是性能最好的,并且扩展性最好。

    另一种方法是从 MarkLogic 外部编排您的计算。否则,您最终要么淹没任务队列,要么遇到超时限制,或两者兼而有之。 Corb2DMSDK 之类的工具可能会对此有所帮助。

    注意:您确实可以使用&lt;result&gt; 选项让生成等待结果,但可以使用&lt;result&gt;true&lt;/result&gt;&lt;result&gt;{fn:true()}&lt;/result&gt;(注意fn:true 后面的括号,它是一个函数)。

    HTH!

    【讨论】:

    • 即使我以后不使用变量 $bs,你确定让 $doc := doc("/count,xml") 行会等到所有生成任务完成。跨度>
    【解决方案2】:

    根据给定的要求,无法区分在 10,mil 文档中编写一次 查询 的最终结果与在 查询 1 个文档之后编写结果之间的区别一次。由于您的示例没有写入查询的文档,因此它不需要生成也不需要在单独的线程或事务中运行,正如 HTH 所说,您可以使用聚合函数对整个集合进行单个查询,计算最终结果并将其存储在 1 次操作中。这可能会运行得非常快(或者可以做到)。

    如果要求实际上是必须查询每个单独的文档,然后依次写入另一个共享文档——这只能通过使用单独的事务串行来观察。它会非常慢,几乎可以肯定比调用事务的超时时间更长。这意味着您必须从外部编排它——如果要求是同一个调用者启动进程和完成它(一个高度实现特定的要求,如果 true 可能除了给定的含义之外还有其他含义)。

    可以实现但仍然非常缓慢的方法是对更新的共享文档进行外部查询轮询,并在工作完成后返回“成功”。 但是同样,对于这么多文档,如果您为每个文档强制写入事务,则它会花费更长的时间(或者至少不容易保证不会花费更长的时间),那么单个事务超时,因此必须从“外部”调用。

    这是我建议重新审视需求以确定所需的核心功能/结果的地方,以及是否确实需要完全按照所述实现,而不是实现所需结果的性能更高的实现。 如果所需的核心功能是每个查询都通过文档更新进行“检查点”,那么还需要考虑其他影响,例如事务回滚。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-14
      • 1970-01-01
      • 2019-06-16
      • 2020-06-10
      • 1970-01-01
      相关资源
      最近更新 更多