代码之家  ›  专栏  ›  技术社区  ›  jbrehr

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

  •  0
  • jbrehr  · 技术社区  · 6 年前

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

    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>')
    

    • 有700多个TEI文档,每个都有 <TEI xml:id="foo_1.xml">

    • <persName role="dep" nymRef="#unique_foo_name"> (文档中不总是在同一位置)

    • 单独的XML文档 codes_people.xml 包含1500+xml:ids of 与众不同的人

    函数执行以下操作:

    1. tei:TEI/@xml:id 以及 tei:persName[@role="dep"]/@nymRef

    2. tei:persName[@role=“dep”]/@nymRef 我在书里查名字 codes_people.xml/tei:person/xml:id="unique_foo_name"

    这一切都返回了预期的结果…除了它真的,真的很慢(4秒)。显然,我是在本地计算机上进行测试,而不是在服务器上进行测试,但我希望在更强大的服务器上进行测试之前优化查询。

    ExistDB版本:3.3.0

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

    <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中所有文件的链接。

    2 回复  |  直到 6 年前
        1
  •  2
  •   duncdrum    6 年前

    replace() 而不是 some/@path[. = 'xyz'] . 简单地使用 fn:id() 而不是

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

    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>
    

    <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>
    

    结果索引实际上是可用的

    /Users/HALmob/pCloud Drive/Screenshots/Screen Shot 2018-10-15 at 01.30.42.png

    你可以下载一个运行你的代码的工作应用程序 here

        2
  •  0
  •   jbrehr    6 年前

    我试图通过替换某些 for let concat() :

    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>')
    

    这些调整使查询执行时间缩短了0.5秒(现在是3.5秒)。

    $persname )查询将在.17秒内执行。文件的查找 codes_people.xml 似乎是瓶颈。

    <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>
    

    从查询探查器查看:

    View from Query Profiler