Performance 在XQuery中,如何避免分页简单查询的性能恶化?
我有一个ML数据库,其中包含数万个文档,还有一个查询,它为所有文档或这些文档的子集返回一些简单的计算值。文档计数已增长到“所有文档”选项不再可靠地运行而不超时的程度,并且随着文档计数的增长,情况只会变得更糟。显而易见的解决方案是客户端应用程序使用另一个表单并对结果进行分页。这是一个离线批处理过程,所以总体速度不是问题——我们只想保持单个请求的正常 查询的分页版本非常简单:Performance 在XQuery中,如何避免分页简单查询的性能恶化?,performance,xpath,xquery,marklogic,Performance,Xpath,Xquery,Marklogic,我有一个ML数据库,其中包含数万个文档,还有一个查询,它为所有文档或这些文档的子集返回一些简单的计算值。文档计数已增长到“所有文档”选项不再可靠地运行而不超时的程度,并且随着文档计数的增长,情况只会变得更糟。显而易见的解决方案是客户端应用程序使用另一个表单并对结果进行分页。这是一个离线批处理过程,所以总体速度不是问题——我们只想保持单个请求的正常 查询的分页版本非常简单: declare namespace ns = "http://some.namespace/here" declare v
declare namespace ns = "http://some.namespace/here"
declare variable $fromCount external;
declare variable $toCount external;
<response> {
for $doc in fn:doc()/ns:entity[$fromCount to $toCount]
return
<doc> omitted for brevity </doc>
} </response>
声明命名空间ns=”http://some.namespace/here"
声明变量$fromCount external;
声明变量$toCount external;
{
对于fn:doc()/ns:entity[$fromCount到$toCount]中的$doc
返回
为简洁起见省略
}
问题是,查询速度越慢,通过所请求页面的文档集越远;大概是因为它必须按顺序加载每个文档,所以在开始构建响应之前,检查它是否是正确的类型并迭代直到找到它的$fromCount
ns:entity
s
一个缺点是数据库中还有其他类型的文档,因此仅使用fn:doc不是一个现实的选项(尽管它们位于不同的目录中,所以xdmp:directory()
可能是一个选项;我将对此进行研究。)
目前在ns:entity
元素上也没有索引;那会有帮助吗?它始终是文档的根节点,文档非常大,因此我关心索引的大小。另外,(这个查询的慢部分)对元素的值不感兴趣,只对它的存在感兴趣
我曾考虑使用search:
api进行内置分页,但对于一个旨在匹配所有文档的查询来说,这似乎有些过分;当然可以手动构造search:search()
将在内部生成的查询
看起来我真正需要的是数据库中某一类型的所有根节点的有效列表。Marklogic有这样的东西吗?如果不是,索引能解决问题吗
Edit:在我的例子中,答案是使用
xdmp:directory()
选项,因为ML显然存储了一个所有文档的快速内存列表。不过,如果有一个更普遍的解决方案,它肯定会引起人们的兴趣,因此我将把问题留在这里。您的分析是正确的:
大概是因为它必须按顺序加载每个文档,所以在开始构建响应之前,检查它的类型是否正确,并迭代直到找到$fromCount ns:entitys
通常的答案是cts:search
加上unfiltered
选项。您发现xdmp:directory
的速度更快,但是您应该仍然能够将分页时间测量为O(n),即使比例更小。请参阅-基本上,数据库是在防止返回误报,除非您告诉它不要返回
另一种方法可能是使用
cts:uri
及其limit
选项,但这可能需要根据起始值而不是页面计数来管理分页状态。例如,如果第1页上的最后一项是“cat”,则在调用下一页的cts:uri
时,可以使用“cat”作为arg2。您也可以使用分页开始停止值。这仍然是O(n)-但规模要小得多。如果你能详细说明你的查询应该做什么,那会有所帮助。是的,ns:entity上的元素范围索引可能有助于加快分页查询的速度。另外,如果您只对元素的存在感兴趣,而不关心它的值,并且每个xs:entity都是一个片段,那么xdmp:exists()可能是最快的确定方法。如果您确实打算搜索文档,那么搜索API并不是真的过分,因为它提供了优化、分页搜索以及其他功能——为什么要重新发明这个轮子?