问题描述
在多个级别执行连接时,我遇到了一个奇怪的性能问题,比如我有一个巨大的 xml,我需要从中执行连接(在那个巨大的 xml 中的记录上,大约几千个)并定义 4 个层次结构级别(父级) /儿童关系)。但是,三个级别的联接(每个级别一个联接)工作正常,但第 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>
我在下面使用的示例加入代码:
Level 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
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
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,for $level3-item in /items/item[level = 3 and parentitem = $level2-item/itemno]
return
<addons>
{
$level3-item!(itemno,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,$level + 1)
}
};
<items>
{
local:nest(/)
}
</items>