我正在使用BaseX XML数据库,并且有很多XML数据,大约有5万个各种大小的文件。但是,我实现的本地功能之一是计算量大。不幸的是,这对我的工作至关重要。
假设每个学生都有5万个文件,每个学生都有一个名为的属性friend
。我想为每个学生找出该学生有多少个朋友。
以下是一些示例代码:
declare variable $context := /Students
declare function local:CalculateFriends($student)
{
let $studentName := $student/@Name
return fn:count($context[@friend = $studentName])
}
for $s in $context
let $numberOfFriends := local:CalculateFriends($s)
return <Student Name = '{$s/@Name}' NumberOfFriends = '{$numberOfFriends}' />
此代码工作正常的一个单一的学生。对于1000名学生,大约需要5分钟。想象一下有5万名学生。它崩溃或超时,我无法调试它。离开它计算一夜,然后回来,什么也没发生。
有没有优化的方法?由于使用@friend = $studentName
它,因此利用了属性索引(已启用)。在大学修完并行课程后,我的第一个想法是将count和flwor语句并行化为块,类似于OpenMP。但是经过一些研究,它似乎并不支持并行查询。
有人对如何解决此问题有任何想法吗?
谢谢!
编辑:XML结构的示例
<Student Name="Kevin" friend="Alvin" BirthDate="1985-06-29" etc..>
<More meta data> ....... />
</Student>
似乎可以将这一问题视为一个分组问题,其中必须计算组的成员,以便您尝试是否
let
$friendsMap as map(xs:string, xs:integer) :=
map:merge(
for $student in $context
group by $friend := $student/@Friend/string()
return map { $friend : count($student) }
)
for $s in $context return <Student Name = '{$s/@Name}' NumberOfFriends = '{$friendsMap($s/@Name)}' />
鉴于分组通常通过使用键来提高效率而得到支持,因此其性能更好。
不知道它是否对解决BaseX和特定问题有帮助,而是发布答案而不是注释来以某种可读的方式建议代码。
在您发布的代码段中,唯一的另一个问题似乎是该示例Friend
在XPath搜索时具有一个拼写的属性@friend
,不确定是否是问题中的错字,或者是索引不起作用的原因。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句