2011-09-15 19 views
2

我有一个XQuery性能问题,我希望有人可以提供帮助。XQuery性能 - 无序的答案?

下面的代码工作正常,但如果可能的话我想提高性能。 它在做什么... - 得到在命中 然后 中发现的prodname属性的所有不同值 - 计算出每个不同值在匹配中发生的次数 - 按顺序返回这些不同的值总共为每个

我有时在$命中有多达12000个项目,所以整个过程可能需要一段时间(反正比我更喜欢它)。

我读过使用无序表达式/函数可以显着提高性能。 所以,我的问题是,是否有一种方法可以改善以下代码的性能 - 使用无序或任何其他方式 - 以及需要进行哪些编码更改? 我仍然需要“由$ d为了”让行,以保持不同值的字母顺序对返回

let $tempResult := 
for $d in distinct-values($hits/ancestor-or-self::DOCUMENT/@prodname) 
    let $q := $hits/ancestor-or-self::DOCUMENT[@prodname = $d]  (: all the hits where prodname attribute has value of $d :) 
     order by $d 
     return <item zprodname="{$d}" zprodnamenum="{count($q)}"/> 

回答

2

XQuery的优化千差万别从一个产品到另一个和技术来提高性能在一个产品上可能与另一个产品有很大不同。所以如果没有(a)知道你使用的是什么产品,并且(b)对该产品的优化器有相当详细的知识,那么你就不能回答这个问题。

我没有看到为什么“无序”应该有助于查询性能的特殊原因,但如果您想查明,请尝试一下并查看。

我会试图改进这个查询的第一件事是将$ hits/ancestor-or-self :: DOCUMENT(或者$ hits/ancestor-or-self :: DOCUMENT/@ prodname)变成一个变量。这可能会对某些产品产生影响,或者可能不会。

不幸的是,XQuery 1.0除了这种“嵌套循环”风格外,没有其他方式可以编写分组查询。如果您无法执行该操作,请考虑使用XSLT 2.0 xsl:for-each-group指令,该指令的效率更高,因为您正在准确说出您想要的内容,只需要一次传递数据。

1

对于Michael的观点,在MarkLogic中,这种方法是通过索引来解决这个问题,因为您可能会获得数百万个物品的计数,并且基数可能非常低。下面是它看起来像MarkLogic扩展:

for $d in cts:element-attribute-values(xs:QName("your-element"),xs:QName("prodname"),(),"frequency-order") 
return <item zprodname="{$d}" zprodnamenum="{cts:frequency($d)}"/> 

其中“频次”返回的项目在频率的顺序,但你可以省略的说法,并让他们回到标顺序。

这是一种常见的编码模式,适用于需要多面导航的搜索应用程序(请参阅www.markmail.org中的基于XQuery的示例,其中日期直方图和构面均使用此方法)。我们在与MarkLogic一起提供的SearchAPI中打包了一些编码最佳实践,以便构建这种接口声明式 - 您只需使用XML文档指定参数,然后XQuery编写适当的代码(类似于上面的示例)和你回来和XML负载。