1

假设您在基于 XQuery 的 XML 数据库中有大量记录:

<widgets>
   <widget id="1" name="Foo Widget" price="19.99" />
   <widget id="2" name="Bar Widget" price="29.99" />
   <widget id="3" name="Baz Widget" price="39.99" />
   <!-- etc. -->
</widget>

我所说的“大量”是指一百万或更多。

您希望使用 XQuery 从列表中随机检索一项:

let $widgets := for $widget in //widgets/widget
  order by util:random()
  return $widget

for $val in subsequence($widgets, 1, 1)
  return $val

当记录数量增加时,评估会花费大量时间来运行,因为它似乎从数据库中加载所有内容并在内存中重新排序。我认为这可能是O(n log 2n)。令人叹息的缓慢。

有没有更懒惰,更好的方法来做到这一点?

有“计算项目数量,然后随机选择一个从零到计数的数字”的方法,我宁愿避免这种方法。

理想情况下,如果有某种功能,数据库可以做到这一点:

let $widgets := for $widget in //widgets/widget
  order by util:random()
  limit 1
  return $widget

我猜这将是 FLOLWR。但它不在 XQuery 规范中,尽管它在 SQL(或者实际上是 SPARQL 或许多其他查询语言)中可能是很常见的事情。

有没有办法得到这个?添加 where 子句就可以了,但是 where 子句在 order 子句之前被评估,这并没有真正的帮助。

有什么建议么?(发送 XQueries 的应用程序是用 Java 编写的,而 XML 数据库是 eXist,如果这有助于更多的曲线球、现成的想法的话。)

4

1 回答 1

3

如果您不使用中间变量,优化器可能会做得更好,但这是一个很大的可能。

subsequence(
 for $widget in //widgets/widget
  order by util:random()
  return $widget
 ,1,1)

我怀疑“你宁愿避免的方法”会表现得更好,但证明是在基准测试中。

//widgets/widget[util:random(count(//widgets/widget))]
于 2011-08-30T17:25:51.130 回答