Есть ли более эффективный XQuery здесь для удаления? - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть большая база данных eXist-db, в которой я реализую некоторые функции для управления данными внутри.

Соответствующая информация здесь:

Есть 2000 клиентов.
Каждый клиент имеет доступ к 400 документам.
Теперь каждый документ имеет 20 языков.

Итак, у меня есть 2000 XML, у каждого есть что-то вроде этого:

<customer name="foo">
    <document num="A01" subscribed="Y">
      <languages>
        <lang subscribed="N">Arabic</lang>
        <lang subscribed="Y">Polish</lang>
... and so on for 400 documents for 20 languages ...

Теперь я пытаюсь написать xQuery, потому что мне нужно отменить язык.Это означает, что мне нужно по существу удалить в 2000 файлах для каждого документа , имя которого определено.

Итак, что-то вроде этого:

 for $langs in $g:collection.customers//lang[text()=$deletelang]
 return update delete $langs

Но это занимает вечно ина самом деле требует огромного количества памяти.Конечно, если посмотреть на это ... $ langs будет 2000 * 400 = 800 000 единиц.

Я бы отметил, что существует индекс диапазона, который содержит:

<create qname="lang" type="xs:string" nested="no"/>

Но все же, это то, чтоУдалить запрос настолько неэффективно, что по существу он не может быть выполнен с 800 000 элементов или есть какой-то другой способ, который должен быть написан?

Обновление I

Так что я немного изменилпросто посмотрите.

1) В комментарии я изменил на "."из текста ()

2) Я добавил подпоследовательность (), окружающую это, для проверки различных размеров >>

for $langs in subsequence($g:collection.customers//lang[.=$deletelang],1,30000)

1-30000 = 24 с

, поэтому запустил всю коллекциюсейчас = 110 с

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Прошло много времени с тех пор, как мне пришлось делать массовые удаления.Но, по крайней мере, в версии 2.2 eXist я мог сделать:

let $langs := $g:collection.customers//lang[.=$deletelang]
return update delete $langs

Не было необходимости циклически просматривать их все.

В отдельном примечании я бы сделал полную резервную копию перед выпуском такоймассовые удаления, просто чтобы убедиться, что все идет хорошо.

Надеюсь, это поможет.

0 голосов
/ 11 февраля 2019

Вам потребуется профилировать запрос, чтобы точно определить, на что он тратит больше всего времени, но возможно, что использование text() приводит к короткому замыканию способности механизма использовать индекс диапазона и, следовательно, загружает все эти документы вmemory.

text() выбирает текстовые узлы, и в элементе может быть более одного текстового узла.то есть: element lang { text { 'Pol' }, text { 'ish' } } приведет к элементу, который выглядит как <lang>Polish</lang>, но имеет два текстовых узла и потерпит неудачу в предикате, который предполагает, что есть только один: [text() = 'Polish'].

Попробуйте использовать точку в своем предикате: [. = $deletelang].

Также возможно, что в базе данных есть дополнительные издержки для одновременного совершения такого большого обновления.Если не критично, что удаление будет выполнено атомарно, вы можете улучшить производительность путем пакетирования обновлений.

...