使用XPath查询XML列的T-SQL非常慢 - 如何改进或替代?

cap*_*cin 3 xml t-sql sql-server xpath

我有一个包含XML数据类型列的表.现在,方法是使用XPath来查询XML中的值.不幸的是,这种方法变得极其缓慢.

该表有大约500,000行.它实际上是一个每天接收新数据的临时表,因此在列上应用XML索引是不切实际的 - 每日INSERT操作需要数小时才能完成.没有索引,它会在大约一分钟内完成.

是否有任何替代方法可以更快地查询此XML数据?

mar*_*c_s 7

XML中有多少项需要定期查询?一些??

我们选择面临同样问题的解决方案是:

  • 创建一个以XML参数作为输入的存储函数
  • 在该函数中,使用XQuery/XPath从XML中提取所需的信息
  • 在表上创建一个引用该函数的计算持久列

通过这种方式,我们提取了三个,四个最常用的信息项(在我们的例子中通常只是一个INT),并将它们作为基表上的列提供.由于它们是持久的,因此只有在XML内容发生变化时才会在每次访问时重新计算它们.而且由于它们是持久存在的,如果需要,你可以在它们上面加上常规的非聚集索引.

例:

我们有一个从XML中提取BIT的函数,告诉我们给定的合同是否有VPN连接:

CREATE FUNCTION dbo.GetVPNFlag(@Data XML)
RETURNS BIT
WITH SCHEMABINDING
AS BEGIN
  DECLARE @VPNFlag BIT

  SELECT  
    @VPNFlag = ISNULL(@Data.value('(EntryIP/VPNOption)[1]', 'bit'), 0)

  RETURN @VPNFlag
END
Run Code Online (Sandbox Code Playgroud)

给定一个XML,这将选择VPN标志并返回它.接下来,我们在基表上创建了一个计算持久列:

ALTER TABLE dbo.ContractData
  ADD IsVPN AS dbo.GetVPNFlag(XmlData) PERSISTED
Run Code Online (Sandbox Code Playgroud)

在这里,我们将表中的XmlData内容传递ContractData给函数.我们回来了一个BIT,它存储IsVPNContractData表格的列上.

我们现在可以轻松地获得与VPN的所有合同:

SELECT (list of fields) 
FROM dbo.ContractData
WHERE IsVPN = 1
Run Code Online (Sandbox Code Playgroud)