如何在 FLWOR(并行化)中优化 XQuery fn:count()?

How to optimize XQuery fn:count() in FLWOR (Parallelize)?

我正在使用 BaseX XML 数据库并且有很多 XML 数据,大约 50 000 个不同大小的文件。 但是,我实现的一个本地功能是计算量大。不幸的是,它在我的工作中非常重要。

让我们假设每个学生有 50 000 个文件,并且每个学生都有一个名为 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 分钟。想象一下 50 000 名学生。它要么崩溃要么超时,我无法调试它。让它计算了一夜,然后回来,什么也没发生。

有没有办法优化这个?由于使用 @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,不确定这是否是问题中的拼写错误或者可能是索引不起作用的原因。