XQuery - оптимизация неэффективной стратегии запросов (в eXist-db) - PullRequest
0 голосов
/ 01 ноября 2018

Среда: eXist-DB 4.4 / Xquery 3.1

У меня есть сотни документов tei: xml, в которых закодированы именованные объекты persName и placeName. Документы в

 collection("db/fooapp/data")

Каждый экземпляр persName и placeName имеет атрибут @nymRef, который содержит одно значение, которое ссылается на xml:id в основных документах:

 db/fooapp/data/codes_persons.xml

 db/fooapp/data/codes_places.xml

Эти основные документы содержат, среди прочего, каноническое имя каждого человека или места.

Я часто делаю одиночные поиски для определенного имени, например

let $x := some @nymRef

let $y := doc(db/fooapp/data/codes_places.xml)//tei:place[@xml:id=$x]//tei:placeName/text()

return $y

Но бывают случаи, когда мне нужно это делать, перебирая огромные списки. Например, для всех документов мне нужно вывести id для seg, и у него есть (или несколько) дочерний элемент placeName/@nymRef:

 <seg xml:id="fooref">some text<placeName nymRef="fooplace"/>some text</seg>

Задача состоит в том, чтобы получить все seg/@xml:id, а затем найти и вывести каноническое имя любого placeName/@nymRef под ним. Это приводит к многочисленным поездкам в оба конца, которые действительно неэффективны, но я не знаю других способов сделать это в eXist-DB. Дорогая поездка туда и обратно выражена в let $c, циклически через return:

let $coll := collection("db/fooapp/data")

for $a in $coll//seg

    for $b in $a//placeName

        let $c := $doc("db/fooapp/data/codes_places.xml")//tei:place[@xml:id=$b/data(@nymRef)]//tei:placeName/text()

        return 
              <tr>
                <td>{$a/@xml:id}</td>
                <td>{$c}</td>
              </tr>

Это может добавить до сотен циклов для одного вывода таблицы.

У меня нет возражений против реструктуризации задачи в несколько функций, если это необходимо.

Большое спасибо заранее.

1 Ответ

0 голосов
/ 02 ноября 2018

Пожалуйста, предоставьте нам входной xml и желаемый вывод, иначе нет способа переписать ваш запрос. Нам также нужно увидеть вашу конфигурацию индекса.

Несколько общих советов, как избежать обходов:

  • Прежде всего, см. Мой предыдущий ответ на ваш вопрос об использовании ft:query(). При выполнении [@xml:id=$b/data(@nymRef)] существует использование индексы или вы заставляете его делать сравнение строк без индекс настроен на эту строку?

  • id() - самый быстрый способ поиска xml:id значений

  • distinct-values ваш друг только для просмотра каждого отдельного ключ: значение пары один раз.

  • Используйте один цикл for, чтобы избежать итерации по нескольким данным раз.

  • По возможности используйте более ограничительные выражения XPath, // вероятно, загружает много ненужных данных в память.

Все это и многое другое можно найти в документации

...