SQL Server 2008 中 xpath 的性能问题

Alb*_*nbo 7 performance sql-server-2008

我有一个包含大量大型 xml 文档的表格。

当我运行 xpath 表达式从这些文档中选择数据时,我遇到了一个特殊的性能问题。

我的查询是

SELECT
p.n.value('.', 'int') AS PurchaseOrderID
,x.ProductID 
FROM XmlLoadData x
CROSS APPLY x.PayLoad.nodes('declare namespace NS="http://schemas.datacontract.org/2004/07/XmlDbPerfTest"; 
/NS:ProductAndRelated[1]/NS:Product[1]/NS:PurchaseOrderDetails[1]/NS:PurchaseOrderDetail/NS:PurchaseOrderID[1]') p(n)
Run Code Online (Sandbox Code Playgroud)

查询需要 2 分 8 秒。

当我[1]像这样删除单个出现节点的部分时:

SELECT
p.n.value('.', 'int') AS PurchaseOrderID
,x.ProductID 
FROM XmlLoadData x
CROSS APPLY x.PayLoad.nodes('declare namespace NS="http://schemas.datacontract.org/2004/07/XmlDbPerfTest"; 
/NS:ProductAndRelated/NS:Product/NS:PurchaseOrderDetails/NS:PurchaseOrderDetail/NS:PurchaseOrderID') p(n)
Run Code Online (Sandbox Code Playgroud)

执行时间降至仅 18 秒。
由于[1]-nodes 在文档中的每个父节点中只出现一次,因此除了排序之外结果是相同的。

第一个(慢)查询的实际执行计划是 计划查询 1

第二个(更快的)查询是

在此处输入图片说明

查询 1全屏查询 2全屏

据我所见,有查询[1]的执行与没有查询的执行相同,但增加了一些额外的计算步骤来查找第一项。

我的问题是为什么第二个查询更快。
我原以为查询的执行会在[1]找到匹配项时提前中断,从而减少执行时间而不是相反。
是否有任何原因导致执行不会提前中断[1],从而减少执行时间。

这是我的桌子

CREATE TABLE [dbo].[XmlLoadData](
    [ProductID] [int] NOT NULL,
    [PayLoad] [xml] NOT NULL,
    [Size]  AS (len(CONVERT([nvarchar](max),[PayLoad],0))),
 CONSTRAINT [PK_XmlLoadData] PRIMARY KEY CLUSTERED 
(
    [ProductID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
       IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, 
       ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

编辑:
来自 SQL Profiler 的性能数据:

查询 1:

CPU     Reads   Writes  Duration 
126251  1224892 0       129797
Run Code Online (Sandbox Code Playgroud)

查询 2:

CPU     Reads   Writes  Duration 
50124   612499  0       16307
Run Code Online (Sandbox Code Playgroud)

GSe*_*erg 2

第二个查询使用并行性。也就是说,它的成本足以让优化器对额外的开销视而不见。

我猜第二个查询告诉优化器“转储所有内容”,这是通过并行扫描执行的。SQL Server 喜欢在被要求时以这种方式“转储所有内容”。
而第一个查询要求“分析然后给出一些”。无论如何,优化器无法知道只有一个节点,因此它最终选择的执行计划非常不同。

我想说这类似于一次表扫描比多次索引查找便宜的情况。