XML 加载缓慢。使用以属性为中心的映射读取 XML 文件时使用 text()
XML load is slow. Using text() when reading XML file with attribute-centric mapping
我正在将 XML 文件读入数据库。它工作正常但速度很慢。我想知道我是否可以使用 text()
来加快处理速度,类似于 post 中的解决方案:Xml select query xpath is slow.
然而,我的问题是解决方案是 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)
我正在读取的文件是13MB,读取它需要3.5个小时。
由于无法像您那样测试那么多行,我会给您这个脚本来试用 (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]
选择器选择第一个这样的元素。
我正在将 XML 文件读入数据库。它工作正常但速度很慢。我想知道我是否可以使用 text()
来加快处理速度,类似于 post 中的解决方案:Xml select query xpath is slow.
然而,我的问题是解决方案是 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)
我正在读取的文件是13MB,读取它需要3.5个小时。
由于无法像您那样测试那么多行,我会给您这个脚本来试用 (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]
选择器选择第一个这样的元素。