Загрузка XML медленная.Использование text () при чтении XML-файла с атрибутно-ориентированным отображением - PullRequest
2 голосов
/ 30 мая 2019

Я читаю в файле XML в базу данных. Работает нормально, но очень медленно. Мне было интересно, могу ли я использовать text(), чтобы ускорить процесс, аналогично решению, приведенному в этом посте: Xml выбор запроса xpath медленный .
Моя проблема, однако, заключается в том, что решение для XML с элементно-ориентированным отображением, в то время как у меня атрибут-ориентированное отображение, поэтому я не уверен, как использовать text() в моем случае.

XML выглядит так

<Level1>
    <Level2 name="l2_name">
        <Level3 name="l3_name">
            <Level4 name="l4_name">
                <Level5 name="l5_name">
                    <Level6_1 name="l6_1_name" value="l6_1_value"/>
                    <Level6_2 name="l6_2_name" value="l6_2_value"/>

Я использую следующий код

declare @x xml

select @x = c1 
from openrowset(bulk 'd:\file.xml', single_blob) as table1(c1);

select
    c.value('@name', 'varchar(20)') as [col1],
    c2.value('@name', 'varchar(20)') as [col2],
    c3.value('@name', 'varchar(20)') as [col3],
    c4.value('@name', 'varchar(20)') as [col4],
    c5_1.value('@name', 'varchar(20)') as [col5],
    c5_1.value('@value', 'varchar(20)') as [col6],
    c5_2.value('@name', 'varchar(20)') as [col7],
    c5_2.value('@value', 'varchar(20)') as [col8],
from @x.nodes('Level1/Level2') as t(c)
cross apply c.nodes('Level3') as t2(c2)
cross apply c2.nodes('Level4') as t3(c3)
cross apply c3.nodes('Level5') as t4(c4)
cross apply c4.nodes('Level6_1') as t5_1(c5_1)
cross apply c4.nodes('Level6_2') as t5_2(c5_2)

Файл, который я читаю, имеет размер 13 МБ, и его чтение занимает 3,5 часа.

1 Ответ

1 голос
/ 30 мая 2019

Не имея возможности тестировать столько строк, сколько у вас есть, я дам вам этот скрипт для проверки ( fiddle <> ):

DECLARE @x XML=N'
<Level1><Level2 name="l2_name"><Level3 name="l3_name">
<Level4 name="l4_name"><Level5 name="l5_name">
<Level6 name="l6_name" value="l6_value"/>
<Level6 name="l6_name" value="l6_value"/>
</Level5></Level4></Level3></Level2></Level1>';

SELECT
    x.n.value('../../../../@name', 'varchar(20)') as [col1],
    x.n.value('../../../@name', 'varchar(20)') as [col2],
    x.n.value('../../@name', 'varchar(20)') as [col3],
    x.n.value('../@name', 'varchar(20)') as [col4],
    x.n.value('./@name', 'varchar(20)') as [col5]
FROM
    @x.nodes('/Level1/Level2/Level3/Level4/Level5/Level6') AS x(n);

Это будет явнозапрос для Level6 узлов, затем возврат к значениям атрибутов родителей.Это, скорее всего, быстрее, чем перекрестное применение запросов для каждого отдельного элемента LevelN.


Обновлено, для элементов уровня 6 с разными именами и при условии, что только один такой элемент каждого имени появляется как потомокуровень 5:

DECLARE @x_2 XML=N'<Level1>
    <Level2 name="l2_name">
        <Level3 name="l3_name">
            <Level4 name="l4_name">
                <Level5 name="l5_name">
                    <Level6_1 name="l6_1_name" value="l6_1_value"/>
                    <Level6_2 name="l6_2_name" value="l6_2_value"/>
                    </Level5></Level4></Level3></Level2></Level1>';

SELECT
    x.n.value('../../../@name', 'varchar(20)') as [col1],
    x.n.value('../../@name', 'varchar(20)') as [col2],
    x.n.value('../@name', 'varchar(20)') as [col3],
    x.n.value('./@name', 'varchar(20)') as [col4],
    x.n.value('(./Level6_1/@name)[1]', 'varchar(20)') as [col5],
    x.n.value('(./Level6_2/@name)[1]', 'varchar(20)') as [col6]
FROM
    @x_2.nodes('/Level1/Level2/Level3/Level4/Level5') AS x(n);

Выбирает узлы на уровне 5, возвращает родительские атрибуты для родительских атрибутов, затем выбирает дочерние элементы на основе имени.Выбирает первый такой элемент, используя селектор [1].

...