Xquery 中联接的性能问题

Performance Issue of a Join in Xquery

我在多个级别执行连接时遇到一个奇怪的性能问题,假设我有一个巨大的 xml,我需要从中执行连接(在那个巨大的 xml 内的记录上,大约几千)并定义 4 个层级(Parent/Child 关系)。但是,在三个级别加入(每个级别一个加入)工作正常但在第 4 级别加入需要几个小时才能完成。非常感谢任何意见和指导。谢谢。 例如:来源XML

<items>
<item>
<level>1</level>
<parentref></parentref>
<parentitem></parentitem>
<itemno>123</itemno>
<itemname>Laptop</itemname>
</item>
<item>
<level>2</level>
<parentref>1</parentref>
<parentitem>123</parentitem>
<itemno>111</itemno>
<itemname>Keyboard</itemname>
</item>
<item>
<level>2</level>
<parentref>1</parentref>
<parentitem>123</parentitem>
<itemno>112</itemno>
<itemname>Mouse</itemname>
</item>
<item>
<level>3</level>
<parentref>2</parentref>
<parentitem>112</parentitem>
<itemno>112-1</itemno>
<itemname>Fiber Mouse</itemname>
</item>
<item>
<level>4</level>
<parentref>3</parentref>
<parentitem>112-1</parentitem>
<itemno>112-2</itemno>
<itemname>Mouse Pad and USB</itemname>
</item>
</items>

预期输出:

<items>
<item>
<itemno>123</itemno>
<itemname>Laptop</itemname> -- Level 1 ( Top level always be one record)
<accessories>               ------------------------------- 
    <itemno>111</itemno>
    <itemname>Keyboard</itemname>  -- Both accessories belong to Level 2 ( can be any number of records)
</accessories>                        one of the accessories has two levels ( can be any number of records) 
<accessories>
    <itemno>112</itemno>
    <itemname>Mouse</itemname>
    <addons>
        <itemno>112-1</itemno>
        <itemname>Fiber Mouse</itemname>
        <moreaddons>                             --- Performance issue is at this level of join
            <itemno>112-2</itemno>                    For 500 addons records, I have almost 5000 moreaddons to match in my source xml.
            <itemname>Mouse Pad and USB</itemname>
        </moreaddons>
    </addons>
</accessories>          
</item>

我在下面使用的示例加入代码:

1级:获得基础物品

for $x in input xml
where $x/level=1

第 2 级:获得给定基础物品的配件

for $y in $x
for $i in input xml
where $i/level=2
and $y/itemno = $i/parentitem 

级别 3:获取给定配件的插件

let $p := (for $bv in $i return $bv)
let $lst := (for $id in input xml
             where $ids/level=3 return $id)
return for-each($p,function($p){
if(for-each($lst,function($lst){$p/itemno=$lst/parentitem})=true()
then for $av in input xml
     where $av/level = 3
     and $av/parentitem=$p/itemno

 

第 4 级:获取给定插件的更多插件

let $q := (for $cv in $av return $cv)
let $lsts := (for $ids in input xml
             where $ids/level=4 return $ids)
return for-each($q,function($q){
if(for-each($lsts,function($lsts){$q/itemno=$lsts/parentitem})=true()
then for $dv in input xml
     where $dv/level = 4
     and $dv/parentitem=$q/itemno

直接的嵌套 for..return 方法看起来像

<items>
{
    for $level1-item in /items/item[level = 1]
    return
        <item>
        {
            $level1-item!(itemno, itemname),
            for $level2-item in /items/item[level = 2 and parentitem = $level1-item/itemno]
            return
                <accessories>
                {
                    $level2-item!(itemno, itemname),
                    for $level3-item in /items/item[level = 3 and parentitem = $level2-item/itemno]
                    return
                        <addons>
                        {
                            $level3-item!(itemno, itemname),
                            for $level4-item in /items/item[level = 4 and parentitem = $level3-item/itemno]
                            return
                                <moreaddons>
                                {
                                    $level4-item!(itemno, itemname)
                                }
                                </moreaddons>
                        }
                        </addons>
                }
                </accessories>
        }
        </item>
}
</items>

最终嵌套要求一个函数采用一个级别:

declare variable $names as xs:string* external := ('item', 'acessories', 'addons', 'moreaddons');

declare function local:nest($root as document-node()) as element()*
{
    let $level := 1
    for $item in $root/items/item[level = $level]
    return 
        element { $names[$level] } {
           $item/itemno,
           $item/itemname,
           local:nest($root, $item, $level + 1)
        }
};

declare function local:nest($root as document-node(), $parent as element(item), $level as xs:integer) as element()*
{
    for $item in $root/items/item[level = $level and parentitem = $parent/itemno]
    return
        element { $names[$level] } {
           $item/itemno,
           $item/itemname,
           local:nest($root, $item, $level + 1)
        }
};

<items>
{
    local:nest(/)

}
</items>