从 MarkLogic 调用服务时超时
Timeout while calling a service from MarkLogic
我在 MarkLogic 中构建了一项服务,该服务由下游应用程序使用(GET 方法)。
在 REST 端点中,我们有四个参数,如 startDate、endDate、seqStart 和 seqLength。
必须通过 REST 端点发送的数据总数为 1.5M,我们将以 25,000 个为一批发送它
我注意到两次执行的运行时间不同,这两次执行具有相同的批处理大小和不同的序列开始
1)seq start=1 seqLength=25000 ElapsedTime=40s
2)seq start=100000 seqLength=25000 ElapsedTime=70s
为什么我在具有相同 seqLength
和不同 seqStart
的 REST 调用中得到不同的 Elapsed 值
我在 CTS 查询中使用 fn:subsequence
。这是正常行为还是我需要对服务进行任何更改。
这实际上不仅在 MarkLogic 中而且在许多其他 DBMS 和搜索引擎系统中也是一个常见问题。
您可以在本地运行这样的查询来验证它:
fn:subsequence(cts:search(fn:doc(), cts:true-query(), 1, 10))
然后将经过的时间与查询进行比较,例如:
fn:subsequence(cts:search(fn:doc(), cts:true-query(), 1000000, 10))
本质上,问题是 MarkLogic 必须解决整个查询,然后单独生成每个结果并对其进行分页,直到它完成构建您想要的 page/batch 结果。
加快速度的唯一方法是计算 pages/batches 的总数,然后在查找高于结果页面集 mid-point 的页面时以相反的顺序遍历.
但是,朝向结果集中心的页面仍然总是最慢的。
像下面这样的东西应该通过以相反的顺序构建页面来更快地 return 接近结果集末尾的页面:
let $pageNumber := 1000
let $resultCount := xdmp:estimate(cts:search(cts:true-query()))
let $pageSize := 25000
let $totalPages := $resultCount div $pageSize
let $middlePage := $totalPages div 2
let $reverseOrder := if($pageNumber gt $middlePage) then fn:true() else fn:false()
let $searchOrder := if($reverseOrder) then "ascending" else "descending"
let $start := if($reverseOrder) then ($middlePage * $pageSize) - ($pageNumber * $pageSize - $middlePage * $pageSize) else $pageNumber * $pageSize
let $end := $start + $pageSize
return fn:subsequence(cts:search(fn:doc(), cts:true-query(), ($searchOrder)), $start, $end)
您还可以使用一些其他新颖的技巧来更快地构建导出。
如果您要导出的数据集是完全静态的或未排序的,您可以将唯一的增量 ID 放入每个文档中,例如 1、2 等...那么您只需要 运行:
cts:search(fn:doc(), cta:and-query((cts:element-range-query(xs:QName("id"), ">=" $start), (cts:element-range-query(xs:QName("id"), "<=" $end))
那将 return 只是属于页面的结果。
如果集合未排序,或者说顺序无关紧要,则此方法适用于批量导出。如果顺序确实很重要,那么保持 ID 最新所花费的时间和难度可能不值得,除非对数据集的更改非常罕见。
您可以考虑的另一种方法是使用较小的批次,运行并行处理多个 workers/exporters,然后在完成后自行将导出拼接在一起。听起来你已经在做类似的事情了。我只是建议您继续使用更多并行工作人员进一步扩展它。您可能 运行 遇到的问题是,如果数据集在导出完成之前发生更改,您可能会得到不完整的导出。
我在 MarkLogic 中构建了一项服务,该服务由下游应用程序使用(GET 方法)。 在 REST 端点中,我们有四个参数,如 startDate、endDate、seqStart 和 seqLength。
必须通过 REST 端点发送的数据总数为 1.5M,我们将以 25,000 个为一批发送它
我注意到两次执行的运行时间不同,这两次执行具有相同的批处理大小和不同的序列开始
1)seq start=1 seqLength=25000 ElapsedTime=40s
2)seq start=100000 seqLength=25000 ElapsedTime=70s
为什么我在具有相同 seqLength
和不同 seqStart
我在 CTS 查询中使用 fn:subsequence
。这是正常行为还是我需要对服务进行任何更改。
这实际上不仅在 MarkLogic 中而且在许多其他 DBMS 和搜索引擎系统中也是一个常见问题。
您可以在本地运行这样的查询来验证它:
fn:subsequence(cts:search(fn:doc(), cts:true-query(), 1, 10))
然后将经过的时间与查询进行比较,例如:
fn:subsequence(cts:search(fn:doc(), cts:true-query(), 1000000, 10))
本质上,问题是 MarkLogic 必须解决整个查询,然后单独生成每个结果并对其进行分页,直到它完成构建您想要的 page/batch 结果。
加快速度的唯一方法是计算 pages/batches 的总数,然后在查找高于结果页面集 mid-point 的页面时以相反的顺序遍历.
但是,朝向结果集中心的页面仍然总是最慢的。
像下面这样的东西应该通过以相反的顺序构建页面来更快地 return 接近结果集末尾的页面:
let $pageNumber := 1000
let $resultCount := xdmp:estimate(cts:search(cts:true-query()))
let $pageSize := 25000
let $totalPages := $resultCount div $pageSize
let $middlePage := $totalPages div 2
let $reverseOrder := if($pageNumber gt $middlePage) then fn:true() else fn:false()
let $searchOrder := if($reverseOrder) then "ascending" else "descending"
let $start := if($reverseOrder) then ($middlePage * $pageSize) - ($pageNumber * $pageSize - $middlePage * $pageSize) else $pageNumber * $pageSize
let $end := $start + $pageSize
return fn:subsequence(cts:search(fn:doc(), cts:true-query(), ($searchOrder)), $start, $end)
您还可以使用一些其他新颖的技巧来更快地构建导出。
如果您要导出的数据集是完全静态的或未排序的,您可以将唯一的增量 ID 放入每个文档中,例如 1、2 等...那么您只需要 运行:
cts:search(fn:doc(), cta:and-query((cts:element-range-query(xs:QName("id"), ">=" $start), (cts:element-range-query(xs:QName("id"), "<=" $end))
那将 return 只是属于页面的结果。
如果集合未排序,或者说顺序无关紧要,则此方法适用于批量导出。如果顺序确实很重要,那么保持 ID 最新所花费的时间和难度可能不值得,除非对数据集的更改非常罕见。
您可以考虑的另一种方法是使用较小的批次,运行并行处理多个 workers/exporters,然后在完成后自行将导出拼接在一起。听起来你已经在做类似的事情了。我只是建议您继续使用更多并行工作人员进一步扩展它。您可能 运行 遇到的问题是,如果数据集在导出完成之前发生更改,您可能会得到不完整的导出。