Как оптимизировать XQuery fn: count () в FLWOR (Parallelize)? - PullRequest
1 голос
/ 10 мая 2019

Я использую базу данных XML BaseX и у меня много 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>

1 Ответ

2 голосов
/ 12 мая 2019

Кажется, что эту проблему можно рассматривать как групповую проблему, в которой необходимо подсчитать членов группы, чтобы вы могли попробовать

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, не зная, является ли это опечаткой в ​​вопросе или, возможно, причиной, по которой Индекс не работает.

...