【问题标题】:MSSQL XML Performance IssueMSSQL XML 性能问题
【发布时间】:2016-09-23 07:20:45
【问题描述】:

样本数据:

<Data>
  <row preis="2.4000" anzahl="72.0000" rabatt="0.0000" mwst="16.0000" bez="tägliche Standreinigung" adoku_nr="1694351" adr_nr="95" anmpos_nr="-1" doku_nr="1694351" gen="0" pos="12" preis_vk="2.4000" preis_lp="2.4000" druck="1" artikel_nr="601" artposarten_nr="1" />
  <row preis="330.0000" anzahl="1.0000" rabatt="0.0000" mwst="15.0000" bez="Abwasseranschluß" adoku_nr="500570" adr_nr="95" anmpos_nr="1" doku_nr="500570" gen="0" pos="6" preis_vk="330.0000" preis_lp="330.0000" druck="1" artikel_nr="304" artposarten_nr="1" />
</Data>

我的目标是为 adoku_nr(行的 id)、属性名称、属性值列。

我已经通过

select
  T.C.value('(../@adoku_nr)[1]', 'int') as ID,
  T.C.value('local-name(.)', 'nvarchar(128)') as Name,
  T.C.value('(.)[1]', 'nvarchar(max)') as Value
from @Data.nodes('/Data/row/@*') as T(C)

结果:

ID      Name    Value
1694351 preis   2.4000
1694351 anzahl  72.0000
1694351 rabatt  0.0000
1694351 mwst    16.0000
1694351 bez tägliche Standreinigung
1694351 adoku_nr    1694351
1694351 adr_nr  95
1694351 anmpos_nr   -1
1694351 doku_nr 1694351
1694351 gen 0
1694351 pos 12
1694351 preis_vk    2.4000
1694351 preis_lp    2.4000
1694351 druck   1
1694351 artikel_nr  601
1694351 artposarten_nr  1
500570  preis   330.0000
500570  anzahl  1.0000
500570  rabatt  0.0000
500570  mwst    15.0000
500570  bez Abwasseranschluß
500570  adoku_nr    500570
500570  adr_nr  95
500570  anmpos_nr   1
500570  doku_nr 500570
500570  gen 0
500570  pos 6
500570  preis_vk    330.0000
500570  preis_lp    330.0000
500570  druck   1
500570  artikel_nr  304
500570  artposarten_nr  1

现在我的问题是,如果我在更大的 xml 上执行此查询,在我的情况下为 120 行,它变得超级慢(4 秒),问题似乎是 ID 列,没有它我回到较低的毫秒括号. 有没有办法优化此查询以实现相同的目标但性能更好?

【问题讨论】:

    标签: sql-server xml xpath xquery sqlxml


    【解决方案1】:

    您可以将此需求作为XQuery 包含在您的XPath

    [@adoku_nr=sql:variable("@rowId")]

    declare @data XML=
    '<Data>
      <row preis="2.4000" anzahl="72.0000" rabatt="0.0000" mwst="16.0000" bez="tägliche Standreinigung" adoku_nr="1694351" adr_nr="95" anmpos_nr="-1" doku_nr="1694351" gen="0" pos="12" preis_vk="2.4000" preis_lp="2.4000" druck="1" artikel_nr="601" artposarten_nr="1" />
      <row preis="999" anzahl="999" rabatt="9999" mwst="16.0000" bez="tägliche Standreinigung" adoku_nr="999" adr_nr="95" anmpos_nr="-1" doku_nr="1694351" gen="0" pos="12" preis_vk="2.4000" preis_lp="2.4000" druck="1" artikel_nr="601" artposarten_nr="1" />
    </Data>';
    
    declare @rowId varchar(100)='1694351'; --try with "999" here to get the other row
    select
      T.C.value('(../@adoku_nr)[1]', 'int') as ID,
      T.C.value('local-name(.)', 'nvarchar(128)') as Name,
      T.C.value('(.)[1]', 'nvarchar(max)') as Value
    from @Data.nodes('/Data/row[@adoku_nr=sql:variable("@rowId")]/@*') as T(C)
    

    从我的魔法玻璃灯泡更新

    .nodes() 位于行上,CROSS APPLY r.nodes() 代表您笔直向下走的属性。不需要昂贵的向后导航...

    我假设您正在寻找这个:

    select
      r.value('@adoku_nr', 'int') as ID,
      a.value('local-name(.)', 'nvarchar(128)') as Name,
      a.value('.', 'nvarchar(max)') as Value
    from @Data.nodes('/Data/row') as A(r)
    cross apply r.nodes('@*') AS B(a)
    

    【讨论】:

    • 非常感谢,但我不是在寻找特定的行,而是寻找所有的行。我将更新我的问题以明确这一点
    • @PaulBecker 我想我知道你需要什么。查看我的更新
    • @PaulBecker 最好将 XML 分解为 直接进入深度。任何跳跃都是昂贵的......
    猜你喜欢
    • 2011-10-24
    • 1970-01-01
    • 2021-10-25
    • 2012-03-15
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多