Самый эффективный способ перебора больших XML-документов в BaseX с использованием xquery и FLWOR - PullRequest
1 голос
/ 19 июня 2019

Я столкнулся с интересной проблемой, когда мне нужно просмотреть несколько больших файлов XML (каждый по сотне МБ) и вывести конкретные данные из каждого из элементов, и сделать это как можно быстрее.Примеры:

Points.xml:

<points>
  <point>
    <identifier>bb25c66c-27d0-447f-aaad-bd8290b332fd</identifier>
    <name>A</name>
  </point>
  <point>
    <identifier>f187cc74-2709-4464-995c-b3bdcae46b39</identifier>
    <name>B</name>
  </point>
</points>

Routes.xml:

<routes>
  <route>
    <pointLink xlink:href="urn:uuid:bb25c66c-27d0-447f-aaad-bd8290b332fd"/>
    <name>1</name>
  </route>
  <route>
    <pointLink xlink:href="urn:uuid:f187cc74-2709-4464-995c-b3bdcae46b39"/>
    <name>2</name>
  </route>
</routes>

В разных документах содержатся десятки тысяч элементов точек / маршрутов, и онигораздо сложнее, чем этот, но для этого примера этого отрывка будет достаточно.

Вывод должен быть примерно таким:

1 - A
2 - B

Я не могу изменить сами документы, вот чтоЯ должен работать с, и теперь вопрос - как связать элементы на основе идентификатора настолько эффективно, насколько это возможно?Я говорю о способе сделать это, возможно, о другом способе думать об этом, а не о фактическом коде, так как в конце концов он будет совсем другим.

Я попытался зацикливаться на маршрутах изатем найти точки, используя FLWOR:

for $route in doc('routes.xml')/routes/route
  return concat(
    $route/name/text(),
    ' - ',
    doc('points.xml')/points/point[./identifier/text() = substring-after($route/pointLink/@xlink:href, 'urn:uuid:')]/name/text()
  )

Это не сработало очень хорошо (заняло почти час).Аналогичная история и с этим подходом:

for $route in doc('routes.xml')/routes/route,
    $point in doc('points.xml')/points/point[./identifier/text() = substring-after($route/pointLink/@xlink:href, 'urn:uuid:')]
  return concat(
    $route/name/text(),
    ' - ',
    $point/name/text()
  )

В конце мне нужно будет использовать больше субэлементов из точки / маршрута в выходных данных, поэтому я думаю, что мне придется перебирать их с помощью for, а затем конкатироватьвывод, но, возможно, я ошибаюсь, вот почему я спрашиваю здесь.

Есть ли что-то, что я пропускаю, или просто нет более быстрого способа сделать это?

1 Ответ

1 голос
/ 19 июня 2019

Проблема действительно была в индексации, как сказал Мартин Хоннен в комментарии.Простое создание индекса атрибута (атрибут CREATE INDEX) помогло сократить время запроса с ~ 45 минут до менее секунды.Невероятный.

...