Hug*_*ans 3 performance xpath xquery marklogic
你好MarkLoggers在那里,
我再次向你提问!我有一系列包含邮政编码信息的文件.400.000个文档.文档按文档订购一个邮政编码,每个文档包含400个功能,按类别和变量排序,如下所示:
<postcode id="9728" xmlns="http://www.nvsp.nl/p4">
<meta-data>
<!--
Generated by DIKW for NetwerkVSP ST!P
-->
<version>0.3</version>
<dateCreated>2014-06-28+02:00</dateCreated>
</meta-data>
<category name="Oplages">
<variable name="Oplage" updated="2014-08-12+02:00">
<segment name="Bruto">1234</segment>
<segment name="Stickers">234</segment>
<segment name="Netto">1000</segment>
<segment name="Aktief">J</segment>
</variable>
</category>
<category name="Automotive">
<variable name="Leaseauto">
<segment name="Leaseauto">2.68822210725987</segment>
</variable>
<variable name="Autotype">
<segment name="De Oudere Stadsrijder">4.61734781858941</segment>
<segment name="De Dure Tweedehandsrijder">6.02534919813761</segment>
<segment name="De Autoloze">41.187790998448</segment>
<segment name="De Leasende Veelrijder">0.608035868253147</segment>
<segment name="De Modale Middenklasser">13.1996896016555</segment>
<segment name="De Vermogende Autoliefhebber">4.45283669598206</segment>
<segment name="De Vermogende Kilometervreter">2.07690981203656</segment>
<segment name="De Doelmatige Budgetrijder">17.2048629073978</segment>
<segment name="De Doorsnee Nieuw Kopende Automob">10.1595102603897</segment>
</variable>
...
400 more cat/var/segment element
...
</postcode>
Run Code Online (Sandbox Code Playgroud)
我需要根据postcode元素中的id属性找到docs的子集,并仅返回特定元素.
要返回的元素是cat Oplages var Oplage,我需要段Bruto和Netto
现在我们有一个rest api扩展,但是不够快.
示例查询:
xquery version "1.0-ml";
declare namespace html = "http://www.w3.org/1999/xhtml";
declare namespace p4ns = "http://www.nvsp.nl/p4";
declare namespace wijkns = "http://www.nvsp.nl/wijk";
let $segment := "Bruto"
let $zoeker0 := cts:search(fn:doc(), cts:element-attribute-range-query(xs:QName("p4ns:postcode"), xs:QName("id"), "=", ("2311","2312","2313")))
let $zoeker1 := cts:search(/p4ns:postcode, cts:element-attribute-range-query(xs:QName("p4ns:postcode"), xs:QName("id"), "=", ("2311","2312","2313")))
let $zoeker2 := cts:search(/p4ns:postcode, cts:element-attribute-value-query(xs:QName("p4ns:postcode"), xs:QName("id"), ("2311","2312","2313")))
let $inhoud1 := $zoeker0//p4ns:segment[@name=$segment]
let $inhoud2 := $zoeker1//p4ns:segment[@name=$segment]/text()
let $r1 := cts:search(/p4ns:postcode, cts:element-attribute-range-query(xs:QName("p4ns:segment"), xs:QName("name"), "=", $segment))
return $inhoud2
Run Code Online (Sandbox Code Playgroud)
现在,如果我描述这个测试查询,那么缓慢的部分就是在cts:search返回的de docs中查找"Bruto"段.我知道我应该避免通过xpath在docs中查找元素,但我不知道如何将这两个位组合起来只打出索引...
Profiler结果:
.main:13:44 1446 27 7127 30 7938 @name = "Bruto"
.main:12:44 1446 27 6956 30 7793 @name = "Bruto"
.main:17:11 1 9.3 2431 9.4 2458 cts:search(fn:collection()/p4ns:postcode, cts:element-attribute-range-query(xs:QName("p4ns:segment"), fn:QName("", "name"), "=", $segment))
.main:10:16 1 7.2 1874 7.2 1885 cts:search(fn:collection()/p4ns:postcode, cts:element-attribute-value-query(xs:QName("p4ns:postcode"), fn:QName("", "id"), ("2311", "2312", "2313")))
Run Code Online (Sandbox Code Playgroud)
查询结果:
1234
4567
3456
Run Code Online (Sandbox Code Playgroud)
现在我的问题:
1)"@name ="Bruto""是什么意思,为什么它变慢?
2)理想情况下,我会将docs的搜索与通过xpath查找segment元素组合成一个组合但如果我将$ zoeker放入cts:搜索它是不可搜索的...什么是将我的结果恢复为一个的最佳方法走?
提前thx!
雨果
我看到两个基本问题:太多的数据库访问,这些旅行带回了太多您不想要的数据.目标是最小化数据库查找的数量,并使每个查找尽可能精确.
在这种情况下,您执行数据库查找的主要方式是cts:search
.有几个:可能太多,有时结果从未使用过.我认为其中一些是剩下的实验.在配置文件时,配置干净的代码非常重要.
接下来,大多数探查器时间都在@name=$segment
XPath谓词中.这也是重复的,并没有充分的理由.摆脱重复,它会更快.
然而,出现的另一个原因@name=$segment
是因为MarkLogic索引文档而不是节点.它索引节点的名称和值,但每个索引条目都指向一个文档 - 或者更具体地说是一个片段,但是我们不会去那里.因此,当您有一个文档具有数十或数百个segment/@name
值的索引条目时,所有这些索引条目都指向文档根目录.当您仅请求与特定名称匹配的段时,索引查找与整个文档匹配.因此评估必须遍历每个文档树.这在CPU周期中可能很昂贵,而这正是分析器向您展示的内容.
如果没有对文件进行重组,或者在共同出现的情况下做一些聪明的事情,那就无法解决这个问题.但是,我们可以清理您的查询,并使用完整路径将其转换为单个XPath表达式.让我们看看这是否足够快你的用例.
declare namespace p4ns="http://www.nvsp.nl/p4" ;
(: These might be external parameters. :)
let $segment := "Bruto"
let $ids := ("2311","2312","2313")
return collection()/p4ns:postcode[
@id = $ids]/p4ns:category/p4ns:variable/p4ns:segment[
@name = $segment]/string()
Run Code Online (Sandbox Code Playgroud)
如果我插入您的示例XML并将其id更改为2313
,则返回单个值1234
.分析它在不到1毫秒的时间内显示33个表达式,其中66%的时间通过XPath查找数据库.然而,它仍然需要查看所有segment/@name
值:在这种情况下,其中14个值占10%的时间.
请注意,我没有使用cts:search
任何范围索引.MarkLogic自动为XPath值 - 相等性查找索引节点值.您只需要特殊操作的范围索引:例如构面,排序和不等式查找.
你可以用这个做得更好:
(collection()/p4ns:postcode[
@id = $ids]/p4ns:category/p4ns:variable/p4ns:segment[
@name = $segment])[1]/string()
Run Code Online (Sandbox Code Playgroud)
现在我们告诉评估者,预计只有一场比赛.因此它会在找到之后停止Bruto
,而且在文档的早期.在这种情况下,它是第一个,但平均(...)[1]
应该将表达式的数量减少一半.其他树修剪技术也应该有所帮助:例如,您可以将输入category
和variable
名称添加到输入中,并将它们表示为XPath谓词.
这可能是您备份和审视大局的好时机.你用这个查询试图完成什么?可能有一种更有效的方式来实现您的目标.
如果这是您最常见的用例,那么理想情况下,您将重新构建文档,以便每个id-segment查找都成为可计算的doc($uri)
调用.我不确定在这种特殊情况下这是一个好主意,但我不完全了解您的应用程序.
另一种方法是使用内存中的值索引和https://docs.marklogic.com/cts:value-co-occurrences来避免查看XML.然而,这是一个复杂的方法,我不打算在这里探讨它.
归档时间: |
|
查看次数: |
311 次 |
最近记录: |