执行许多查询时扩展树缓存已满

Expanded tree cache full when performing many queries

我正在实施批处理,需要在 MarkLogic 中执行大量搜索查询以查找要修改的文档。 我正在使用的查询如下所示:

cts:search(/ch:haufe-document,
  cts:and-query((
    cts:element-range-query(fn:QName("http://idesk.haufe-lexware.com/document-meta","rootId"), "=", xs:string($root-id)),
    cts:element-range-query(fn:QName("http://contenthub.haufe-lexware.com/haufe-document","application"), "=", xs:string($APPLICATION-ID))
  ))
)

每个查询的$root-id 都会不同,$APPLICATION-ID 是一个常量值。 通常这些查询 return 少量文档(少于 10 个),有时多达 150 个,但它们仍然工作正常。 只有在连续执行许多此类查询(对于一个批处理作业可能超过 100000 个)时,我才会在某个时候返回这样的错误:

XDMP-EXPNTREECACHEFULL: cts:search(fn:collection()/ch:haufe-document, cts:and-query((cts:element-range-query(fn:QName("http://idesk.haufe-lexware.com/document-meta","rootId"), "=", "HI14429659", ("collation=http://marklogic.com/collation/"), 1), cts:element-range-query(fn:QName("http://contenthub.haufe-lexware.com/haufe-document","application"), "=", "idesk", ("collation=http://marklogic.com/collation/"), 1)), ())) -- Expanded tree cache full on host some-host.cloudapp.net uri /content/idesk/c9103265-0a44-496b-b2b1-617b0b042208/HI14429659.xml

当我手动执行相同的查询时,它运行没有问题,return结果很少(大多数情况下只有一个)。 匹配 /ch:haufe-document 的文档数量约为 300 万,但在处理过程中变化不大(文档仅被修改)。该数据库包含额外的 150 万个元数据文档,这些文档是在处理过程中添加的。

奇怪的是,前两个批处理作业(每个处理 >600000 个文档)运行良好。 但是第三个作业因上述错误而失败,此后只能成功处理非常小的作业(~30000 个文档)。

我已经尝试增加扩展树缓存的大小,但没有帮助。 我也尝试了“未过滤”搜索,但错误仍然存​​在。

如能提示问题所在,我将不胜感激。

更新:有一件事我没有提到,因为我没有意识到它可能是相关的:整个过程是作为 REST 扩展实现的,从 Java 应用程序调用。发出 POST 请求,其中包含 XML 以及要处理的文档 ID 列表。而且这个列表可能会很长(>100000 个条目)。

遇到扩展树缓存错误的查询可能没有提取大量文档。这可能只是压垮骆驼的最后一根稻草

Resolving XDMP-EXPNTREECACHEFULL errors

When the query needs to actually retrieve elements, values, or otherwise traverse the contents of one of these fragments, the fragment is uncompressed and cached in the expanded tree cache.

Consequently, the expanded tree cache needs to be large enough to maintain a copy of every expanded XML fragment that is simultaneously needed during query processing.

The error message XDMP-EXPNTREECACHEFULL: Expanded tree cache full means that MarkLogic has run out of room in the expanded tree cache during query evaluation, and that consequently it cannot continue evaluating the complete query.

根据您的需求和能力,有几个选项可以解决这个问题。

  • 如果您有足够的内存可供分配,您可以提高 ETC 限制并提供更多内存来为这些请求提供服务。
  • 如果您发现一些贪婪且低效的查询同时提取大量文档,请查看是否可以将它们分解为更小的事务。
  • 如果您有太多并发事务处理太多文档,请限制应用程序服务器线程数或降低批处理作业的线程数。
  • 为超过这些限制的 auto-cancellation 个交易配置最大 readSize 限制:https://docs.marklogic.com/guide/performance/request_monitoring#id_10815

看那个大小,你可能不会通过增加内存来解决问题。从表面上看,您实际上是在尝试将整个数据库吸入内存。更多批次等于并行内存中的更多内容。

退后一步,试着弄清楚你想要完成什么。似乎任何试图处理这些结果的人都无法一次完成所有工作,因此请考虑转回引用。

这是一个示例,您可以通过仅返回 URI 来开始。然后调用代码可以在处理每个文档时获取文档等(保持内存使用率较低)

cts:uris((),(),cts:element-query(xs:QName(ch:haufe-document),
   cts:and-query((
       cts:element-range-query(fn:QName("http://idesk.haufe-lexware.com/document-meta","rootId"), "=", xs:string($root-id)),
       cts:element-range-query(fn:QName("http://contenthub.haufe-lexware.com/haufe-document","application"), "=", xs:string($APPLICATION-ID))
     ))
   )
 )

我使用 cts:uris() 作为示例起点。

我找到的解决方案是这样的:我修改了 Java 应用程序,使其不会立即将所有数据发送到 MarkLogic,而是将其分成 10000 个 ID 的块。现在错误消失了。缺点是更改现在是在多个事务中完成的,因此在完成所有操作之前修改就变得可见了。但对于我的用例,这是可以接受的。