首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XQUERY:优化涉及大型集合的查询

XQUERY:优化涉及大型集合的查询
EN

Stack Overflow用户
提问于 2018-10-08 20:08:24
回答 2查看 240关注 0票数 0

我在ExistDB中运行了以下XQUERY (针对遵循TEI模式的XML文档):

代码语言:javascript
复制
xquery version "3.1";

declare namespace tei="http://www.tei-c.org/ns/1.0";

let $data-collection := "/db/apps/deheresi/resources/documents"
let $people-collection := "/db/apps/deheresi/resources/documents/codes_people.xml"

for $msdoc in collection($data-collection)/tei:TEI[contains(@xml:id,'ms609')]

for $ordinal in $msdoc/tei:text/tei:front//tei:div[@type='registry_ordinal']/replace(@n, '#', '')

for $doctype in $msdoc/tei:text/tei:front//tei:div[@type='doc_type']/replace(@subtype, '#', '')

for $folio in $msdoc/tei:text/tei:front//tei:div[@type='folio']/replace(@n, '#', '')

for $nameref in $msdoc/tei:text/tei:body[1]/tei:p[1]/tei:seg[1]/tei:persName[@role = 'dep']/replace(@nymRef, '#', '') 

for $persname in normalize-space(string-join(doc($people-collection)//tei:person[@xml:id = $nameref]))

return concat('<td>',$ordinal,'</td><td>',$folio,'</td><td>',$doctype,'</td><td>',$persname,'</td>')

XML文档的组织:

  • 有700+ TEI文档,每个文档都以<TEI xml:id="foo_1.xml">作为根节点(文档标识符递增foo_1.xml、foo_2.xml、foo_3.xml等)。(总是在同一个地方)
  • 每个TEI文档包含一个标识person <persName role="dep" nymRef="#unique_foo_name">的唯一元素(并不总是在文档中相同的位置)。
  • 一个单独的XML文档codes_people.xml,其中包含不同人员的1500+ xml:id。

该职能的作用如下:

  1. 从每个xml文档获取标识tei:TEI/@xml:idtei:persName[@role="dep"]/@nymRef
  2. 使用tei:persName[@role="dep"]/@nymRef,我在codes_people.xml/tei:person/xml:id="unique_foo_name"中查找名称

所有这些都返回预期的results...except --非常非常慢(4秒)。显然,我是在本地计算机上进行测试,而不是在服务器上进行测试,但是在对功能更强大的服务器进行测试之前,我想优化查询。

按请求添加:

ExistDB版本: 3.3.0

示例输出(最终目标是HTML表)

代码语言:javascript
复制
<td>0001</td><td>1r</td><td>Deposition</td><td>Arnald Garnier</td> 
<td>0002</td><td>1r</td><td>Deposition</td><td>Guilhem de Rosengue</td> 
<td>0003</td><td>1r</td><td>Deposition</td><td>Hugo de Mamiros</td> 
<td>0004</td><td>1r</td><td>Deposition</td><td>P Lapassa senior</td>

在此之前,非常感谢您。

编辑:我已经添加了更多的信息,在下面的自我响应,并链接到所有文件在Dropbox中的评论。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-14 23:32:31

因此,您的代码存在一些问题,这会影响性能。第一个事实是您处理字符串而不是xml路径。当使用replace()而不是some/@path[. = 'xyz']时。只需使用fn:id()而不是replace()就可以将执行时间缩短到1秒以下。

第二个是索引配置文件中缺少的xmlschema命名空间声明,而不是使用这些索引,因为您强制exist处理字符串而不是xml。

第三个事实是,xquery代码不返回格式良好的xml片段,出于性能原因,这始终是个坏主意。

代码语言:javascript
复制
xquery version "3.1";
declare namespace tei="http://www.tei-c.org/ns/1.0";

declare variable $data-collection := "/db/apps/so-52709411/data";

(:always return a well-formed fragment:)
 <table>{

 let $people-collection := doc($data-collection || "/codes_people.xml")

 let $msdoc := collection($data-collection)//tei:TEI[contains(@xml:id,'ms609')]

 for $n in $msdoc
 let $registry := $n//tei:div[@type='registry_ordinal']/data(@n)
 let $type := $n//tei:div[@type='doc_type']/data(@subtype)
 let $folio := $n//tei:div[@type='folio']/data(@n)
 let $nym := substring-after($n//tei:persName[@role = 'dep']/data(@nymRef), '#') 
 let $persName := $people-collection//id($nym)/tei:persName

 return
<tr>
<td>{$registry}</td>
<td>{$type}</td>
<td>{$folio}</td>
<td>{$persName/string()
}</td>
</tr>

}
 </table>

代码语言:javascript
复制
<collection xmlns="http://exist-db.org/collection-config/1.0">
<index xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <range>
       <create qname="tei:persName" type="xs:string"/>
       <create qname="tei:person" type="xs:string"/>
       <create qname="@type" type="xs:string"/>
       <create qname="@role" type="xs:string"/>
       <create qname="@nymRef" type="xs:string"/>
    </range>
</index>
<triggers>
    <trigger class="org.exist.extensions.exquery.restxq.impl.RestXqTrigger"/>
</triggers>
 </collection>

结果显示索引实际上是可用的

但是,数据示例并不足以在重写的xquery之外对性能产生很大影响。因此,即使没有索引,您也应该在小于1s的范围内运行(取决于内存、硬件等,YMMV)。

您可以下载使用代码这里运行的工作应用程序。

票数 2
EN

Stack Overflow用户

发布于 2018-10-09 06:44:44

我试图通过将某些for循环替换为letconcat()来简化Xquery

代码语言:javascript
复制
xquery version "3.1";

declare namespace tei="http://www.tei-c.org/ns/1.0";

declare variable $people-collection := doc("/db/apps/deheresi/resources/documents/codes_people.xml");

let $data-collection := "/db/apps/deheresi/resources/documents"

for $msdoc in collection($data-collection)/tei:TEI[contains(@xml:id,'ms609')]

    let $concat1 := concat('<td>',
               $msdoc//tei:div[@type='registry_ordinal']/replace(@n, '#', ''), 
               '</td><td>', 
               $msdoc//tei:div[@type='doc_type']/replace(@subtype, '#', ''), 
               '</td><td>',
               $msdoc//tei:div[@type='folio']/replace(@n, '#', ''),
               '</td><td>')

    (:  obtain the attribute value of persName[@role = 'dep']/@nymRef   :)
    let $nameref := $msdoc//tei:persName[@role = 'dep']/replace(@nymRef, '#', '') 

    (:  now use the attribute value to lookup a printable name using xml:id in document codes_people.xml :)
    let $persname := normalize-space(string-join($people-collection//tei:person[@xml:id = $nameref]))

return concat($concat1,$persname,'</td>')

这些调整从查询执行时间(现在是3.5秒)中删除了.5秒。

如果去掉最终查找($persname),查询将在.17秒内执行。查找文件codes_people.xml似乎是瓶颈。

编辑:我添加了影响相关元素的以下索引,它们没有产生任何优化

代码语言:javascript
复制
<collection xmlns="http://exist-db.org/collection-config/1.0">
    <index xmlns:tei="http://www.tei-c.org/ns/1.0">
        <range>
           <create qname="tei:persName" type="xs:string"/>
           <create qname="tei:person" type="xs:string"/>
        </range>
    </index>
    <triggers>
        <trigger class="org.exist.extensions.exquery.restxq.impl.RestXqTrigger"/>
    </triggers>
</collection>

查询探查器中的视图:

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52709411

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档