【问题标题】:Alternative to SQL Cross apply because of performance issues由于性能问题,替代 SQL 交叉应用
【发布时间】:2017-07-23 02:04:58
【问题描述】:

我有点墨守成规。我有一个 xml 和 SQl 服务器。我想获取 FBC 的所有值,用逗号分隔。

表的名称是 Table1。存储 xml 的列的名称是 FareDetails。 BookingID 和 ID 是表 1 的其他列。

SELECT
    (PTSD.PSTDNode.value('(FBC)[1]', 'VARCHAR(1024)')  + ',') [text()]
FROM
    [Table1]
    CROSS APPLY [FareDetails].nodes('/AirFareInfo/PTSDPFS/PTSD') PTSD(PSTDNode)
WHERE
    [BookingID] = 123
ORDER BY
    [AirTraveler].ID ASC
FOR XML PATH ('')

但我在数据库中有数百万条记录,这会对性能造成巨大影响。

xml:

<AirFareInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" IPFA="false">
  <PT>Flight</PT>
  <FPMID>0</FPMID>
  <PTID>1</PTID>
  <FS>
    <CID>2</CID>
    <Value>0</Value>
  </FS>
  <TF>
    <CID xsi:nil="true" />
    <Value>0</Value>
  </TF>
  <VF>
    <CID>2</CID>
    <Value>0</Value>
  </VF>
  <VD>
    <CID>2</CID>
    <Value>0</Value>
  </VD>
  <VCR xsi:nil="true" />
  <VC>
    <CID>2</CID>
    <Value>0</Value>
  </VC>
  <VFC>
    <CID>2</CID>
    <Value>0</Value>
  </VFC>
  <VST />
  <VIT />
  <AAPFVDR xsi:nil="true" />
  <CC>
    <CID>2</CID>
    <Value>0</Value>
  </CC>
  <D>
    <CID>2</CID>
    <Value>514.15</Value>
  </D>
  <PD>
    <CID>2</CID>
    <Value>0</Value>
  </PD>
  <EBF>
    <CID>2</CID>
    <Value>0</Value>
  </EBF>
  <CST>
    <DL>
      <ATRID>13</ATRID>
      <OB>
        <CID>2</CID>
        <Value>74.04</Value>
      </OB>
      <OC>
        <CID>2</CID>
        <Value>0.00</Value>
      </OC>
      <OS>
        <CID>2</CID>
        <Value>0.00</Value>
      </OS>
      <OF>
        <CID>2</CID>
        <Value>50.83</Value>
      </OF>
      <OP>
        <CID>2</CID>
        <Value>0.00</Value>
      </OP>
      <C>
        <CID>2</CID>
        <Value>0</Value>
      </C>
      <IBF>false</IBF>
      <D>2014-06-09T14:57:53.521Z</D>
    </DL>
  </CST>
  <CIT />
  <CRMR xsi:nil="true" />
  <CRM>
    <CID>2</CID>
    <Value>0</Value>
  </CRM>
  <TL ATC="Tax" PC="" DEN="User Development Fee - Arrival (UDF)">
    <TID xsi:nil="true" />
    <Amount>
      <CID>2</CID>
      <Value>75.00</Value>
    </Amount>
  </TL>
  <TL ATC="Tax" PC="" DEN="Passenger Service Fee">
    <TID xsi:nil="true" />
    <Amount>
      <CID>2</CID>
      <Value>146.00</Value>
    </Amount>
  </TL>
  <TL ATC="Tax" PC="" DEN="User Development Fee - Departure (UDF)">
    <TID xsi:nil="true" />
    <Amount>
      <CID>2</CID>
      <Value>1681.00</Value>
    </Amount>
  </TL>
  <TL ATC="Tax" PC="" DEN="Cute Fee">
    <TID xsi:nil="true" />
    <Amount>
      <CID>2</CID>
      <Value>50.00</Value>
    </Amount>
  </TL>
  <TL ATC="Tax" PC="" DEN="Government Service Tax">
    <TID xsi:nil="true" />
    <Amount>
      <CID>2</CID>
      <Value>151.00</Value>
    </Amount>
  </TL>
  <TL ATC="Tax" PC="" DEN="User Development Fee - Arrival (UDF)">
    <TID xsi:nil="true" />
    <Amount>
      <CID>2</CID>
      <Value>833.00</Value>
    </Amount>
  </TL>
  <TL ATC="Tax" PC="" DEN="Passenger Service Fee">
    <TID xsi:nil="true" />
    <Amount>
      <CID>2</CID>
      <Value>1132.00</Value>
    </Amount>
  </TL>
  <TL ATC="Tax" PC="" DEN="User Development Fee - Departure (UDF)">
    <TID xsi:nil="true" />
    <Amount>
      <CID>2</CID>
      <Value>76.00</Value>
    </Amount>
  </TL>
  <TL ATC="Tax" PC="" DEN="Government Service Tax">
    <TID xsi:nil="true" />
    <Amount>
      <CID>2</CID>
      <Value>148.00</Value>
    </Amount>
  </TL>
  <PTSDPFS>
    <PTSD IO="false">
      <FBC>AP</FBC>
      <ACD RBD="" ACCID="1" MCT="Super Sale Fare(AP)" INC="false" />
      <ATSID xsi:nil="true" />
    </PTSD>
  </PTSDPFS>
  <PTSDPFS>
    <PTSD IO="false">
      <FBC>AP</FBC>
      <ACD RBD="" ACCID="1" MCT="Super Sale Fare(AP)" INC="false" />
      <ATSID xsi:nil="true" />
    </PTSD>
  </PTSDPFS>
  <RuleDetails>
    <TRS xsi:nil="true" />
    <PP xsi:nil="true" />
    <II xsi:nil="true" />
    <LTD xsi:nil="true" />
  </RuleDetails>
</AirFareInfo>

这种情况下的输出应该是 AP,AP。如何提高性能?

【问题讨论】:

  • 您的 xml 格式不正确,无法使用 xml 类型声明。请阅读此标头“Nodes() 方法应用和效率”simple-talk.com/sql/database-administration/… xml 操作还有一件事,但不是麦酒来回忆一下。
  • 但我在数据库中有数百万条记录...读取 在 XML 中数百万的值不会很快...但是您正在使用 @ 987654324@。您是否将此调用过滤到几条记录? &lt;PTSDPFS&gt; 的数量是固定的(在这种情况下是两个)还是 1:n?内容是 within 这个节点修复还是可能是 1:n 某处?这是一次性行动还是您必须经常做的事情?您可能会使用触发器。维护一个包含您要搜索的值的边表。
  • AirTraveler.ID 来自哪里?
  • @Shnugo : 可以是 1 到 n 我提到的代码在从 sp 调用的 UDF 中。
  • 性能可能来自这里:我提到的代码位于从 sp 调用的 UDF 中 从 SP 调用(标量?)UDF 往往会表现得很糟糕表现。你检查我的答案了吗?如果你可以调用这个inlined,它的性能应该会好很多...

标签: sql sql-server join sqlxml cross-apply


【解决方案1】:

正如我在评论中所说,最佳答案取决于我不知道的许多因素。就像一个快速的镜头,你可以试试这个:

SELECT REPLACE(FareDetails.query(N'data(/AirFareInfo/PTSDPFS/PTSD/FBC)').value('(text())[1]','nvarchar(100)'),' ',',')
FROM Table1
WHERE BookingID=123

XML 方法data() 返回所有找到的text(),以空格分隔(遗憾的是无法更改)。只要您在&lt;FBC&gt; 中的文本不包含它自己的空白,这将有效。

【讨论】:

  • 这个答案给出了输出:AP,A 而不是 AP,AP
  • @PiyushSing 我试过这个,我得到了正确的结果。也许这在某处被剪切(变量到小,其他功能......)
  • 嗨@shnugo,当我们在表中有重复的 bookingid 时,它会失败。例如,BookingID 123 在表中出现了 4 次,并且在 FareDetails(xml) FBC 中有值 a、b、c、 d 对应于 4 个 xml。所有 4 BookingID 的输出应该是 a,b,c,d 。当前输出是 a,用于第 1 个条目,b,用于第 2 个条目,c,用于第 3 个条目,d,用于第 4 个条目。请帮忙。
  • @PiyushSing 请避免变色龙问题!最初的问题没有说明每个 BookingID 有多个记录。在这种情况下,您必须像上面一样阅读所有这些行并将它们连接到一个答案。但是重复值呢?这是一个全新的问题!如果我的回答解决了这个问题。请接受它(在投票柜台下方查看)并开始一个新问题。请将您的样本减少到所需的最低限度!
  • 感谢这个解决方案,我已经发布了单独的问题,请看一下。 stackoverflow.com/questions/42777070/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-01
  • 2011-09-14
  • 2015-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多