假设我有一堆带有根元素的医学期刊,因为medicalJournal.All医学期刊属于mj的收藏,而mj的收藏只有医学期刊。其他类型的期刊也有自己的收藏(physicsJournal>‘pj’)来检索我在世界上最简单的查询的所有医学期刊:
cts:search(/medicalJournal,cts:and-query(()))然而,我的一位同行说,为什么不对'pj‘而不是空和查询进行集合查询,从而添加一个额外的约束。原因之一是,这可能避免获取所有片段is的列表,当我第一次运行集合查询时,查询表显示了一些列表-缓存-遗漏。请告诉我应该采取哪种选择?
发布于 2014-12-07 19:56:56
简单地说,cts:and-query(())没有固有的成本,但是集合查询比可搜索的表达式更快。我完全避免使用可搜索的表达式,因此我将这样写成:
cts:search(collection(), cts:collection-query($journal-collection))更长的答案是,您可以很容易地测试这一点,并从xdmp:plan和'xdmp: query -meters`‘获得一些很好的信息。您还可以使用查询分析。
让我们从插入一些测试文档开始。这使用https://github.com/mblakele/taskbot
(: insert 500k test documents. :)
import module namespace tb="ns://blakeley.com/taskbot"
at "taskbot.xqm" ;
tb:list-segment-process(
(: Total size of the job. :)
1 to 500 * 1000,
(: Size of each segment of work. :)
500,
"test/asset",
(: This anonymous function will be called for each segment. :)
function($list as item()+, $opts as map:map?) {
(: Any chainsaw should have a safety. Check it here. :)
tb:maybe-fatal(),
let $type-list := ('mj', 'pj', 'aj', 'bj', 'cj', 'dj')
let $type-count := count($type-list)
for $i in $list
let $idx := 1 + xdmp:random($type-count - 1)
let $type as xs:string := subsequence($type-list, $idx, 1)
return xdmp:document-insert(
"test/"||$type||"/"||$i,
element article {
element id { $type||$i },
element type { $type },
element { $type } { $i },
element issue { 1 + xdmp:random(99) },
element article { 1 + xdmp:random(999) },
(1 to xdmp:random(9)) ! element article-ref {
xdmp:random(1000) } },
xdmp:default-permissions(),
($type)),
(: This is an update, so be sure to commit each segment. :)
xdmp:commit() },
(: options - not used in this example. :)
map:new(map:entry('testing', '123...')),
(: This is an update, so be sure to say so. :)
$tb:OPTIONS-UPDATE)坐着等待文件的加载。您可以检查ErrorLog.txt以查看进度,或刷新数据库状态。或者看着你的CPU。
一旦加载,这些测试文档就包含了大量冗余。这使我们可以测试检索文档的不同方法。下面是一个需要查看的示例:
<?xml version="1.0" encoding="UTF-8"?>
<article>
<id>mj192462</id>
<type>mj</type>
<mj>192462</mj>
<issue>31</issue>
<article>432</article>
<article-ref>589</article-ref>
<article-ref>812</article-ref>
<article-ref>316</article-ref>
<article-ref>512</article-ref>
<article-ref>380</article-ref>
</article>现在,我倾向于将第一个cts:search参数保留为collection(),并在cts:query参数中执行所有操作。它更易于组合,避免了任何试图突破可搜索表达式的界限的诱惑。因此,我首先要测试cts:search(//mj, cts:and-query(()))是否等同于cts:search(collection(), cts:element-query(xs:QName('mj'), cts:and-query(())))。使用7.0-4.1和xdmp:plan,我看到它们都使用相同的查找,我们可以将其缩写为OR(element(mj), link-child(descendant(element(mj))))。
<qry:final-plan>
<qry:and-query>
<qry:or-two-queries>
<qry:term-query weight="0">
<qry:key>213142789040258053</qry:key>
<qry:annotation>element(mj)</qry:annotation>
</qry:term-query>
<qry:term-query weight="0">
<qry:key>11205365121816230941</qry:key>
<qry:annotation>link-child(descendant(element(mj)))</qry:annotation>
</qry:term-query>
</qry:or-two-queries>
</qry:and-query>
</qry:final-plan>注意,计划中怎么没有与您的cts:and-query(())相对应的任何内容?那是因为这是个小屁屁。像cts:search(/medicalJournal, cts:and-query(()))这样的查询的真正工作是通过处理可搜索的表达式/medicalJournal来完成的。这可能有助于解释为什么我喜欢将可搜索表达式保留为collection()并使用cts:query参数进行匹配。
link-child术语很有趣,但我们现在不要再讨论它了。
相反,让我们来看看其他一些获取mj文章的方法。我们可以对集合mj、type[.='mj']所在的元素或test/mj/上的目录查询进行查询。
collection('mj')
cts:search(collection(), cts:collection-query('mj'))
cts:search(collection(), cts:element-value-query(xs:QName('type'), 'mj')
cts:search(collection(), cts:directory-query('test/mj/', 'infinity'))检查每个表单的xdmp:plan输出,我们看到qry:final-plan显示了前两个表单的两个term-query查找。这看上去很像element-query on mj,但并不总是相同的条款。然后我们看到最后三人每人一人。术语查找驱动查询的复杂性,因此可以说元素查询是集合查询的两倍。
这很大程度上回答了您的问题,我认为:cts:search(collection(), cts:collection-query('mj'))可以比cts:search(collection(), cts:element-query(xs:QName('mj'), cts:and-query(())))更快,因为它可以进行更少的术语查找。
但让我们继续使用最后三个,看看是否有任何理由使用其中的最后三个备选词。集合查找和目录查找都使用URI:、集合URI和目录URI。这些都是非常优化的,所以我们可能期望它们比元素值查找更快。
让我们看看我们是否能够证明这一点,使用xdmp:query-meters。以如下形式运行最后三个表达式的每个表达式:
xdmp:describe(
cts:search(collection(), cts:collection-query('mj')))
, xdmp:query-meters()在本练习中,重点关注xdmp:query-meters对树缓存和列表缓存命中和遗漏的看法。不要过多地关注elapsed-time,因为这在很大程度上取决于缓存了多少索引数据,而我们无法控制它。无论如何,您应该看到所有三个查询的总树命中和错过。我看到了每个9,但重要的是没有区别,因为结果是相同的。但是,列表缓存的命中和遗漏完全不同。对于集合或目录,它等于数据库中的站立数:在我的示例3中。但对于元素值,它是站立数量的两倍:在我的示例6中。因此,其他所有相同的元素值查找都有风险做两倍的I/O,而其他所有查找都不相等: URI查找根本不太可能执行任何I/O操作,因为它们的索引总是保存在内存中。
我们可以得出结论,虽然其他方法都不是非常慢,但通过集合URI或目录URI进行查找是最好的。
https://stackoverflow.com/questions/27340007
复制相似问题