为什么从XML变量中插入 - 选择变量表这么慢?

时间:2010-10-20 14:15:43

标签: sql-server xml sql-server-2008 variables

我正在尝试将XML文档中的一些数据插入到变量表中。让我感到震惊的是,当insert-select需要很长时间时,同一个select-into(批量)运行,并且在执行查询时,SQL Server进程负责100%的CPU使用率。

我看了一下执行计划,并且INDEED有区别。 insert-select添加了一个额外的“表spool”节点,即使它没有分配成本。 “表值函数[XML Reader]”然后得到92%。使用select-into,两个“表值函数[XML Reader]”各得49%。

请解释“为什么会发生这种情况”和“如何解决这个问题(优雅地)”,因为我确实可以批量插入临时表,然后插入到变量表中,但这只是令人毛骨悚然。

我在SQL 10.50.1600,10.00.2531上尝试了这个,结果相同

这是一个测试用例:

declare @xColumns xml
declare @columns table(name nvarchar(300))

if OBJECT_ID('tempdb.dbo.#columns') is not null drop table #columns

insert @columns select name from sys.all_columns

set @xColumns = (select name from @columns for xml path('columns'))

delete @columns

print 'XML data size: ' + cast(datalength(@xColumns) as varchar(30))

--raiserror('selecting', 10, 1) with nowait

--select ColumnNames.value('.', 'nvarchar(300)') name
--from @xColumns.nodes('/columns/name') T1(ColumnNames)

raiserror('selecting into #columns', 10, 1) with nowait

select ColumnNames.value('.', 'nvarchar(300)') name
into #columns
from @xColumns.nodes('/columns/name') T1(ColumnNames)

raiserror('inserting @columns', 10, 1) with nowait

insert @columns
select ColumnNames.value('.', 'nvarchar(300)') name
from @xColumns.nodes('/columns/name') T1(ColumnNames)

非常感谢!

2 个答案:

答案 0 :(得分:19)

这是SQL Server 2008中的一个错误。 使用

insert @columns 
select ColumnNames.value('.', 'nvarchar(300)') name
from @xColumns.nodes('/columns/name') T1(ColumnNames)
OPTION (OPTIMIZE FOR ( @xColumns = NULL ))

此解决方法来自Microsoft Connect Site上的一个项目,该项目还提到了此Eager Spool / XML Reader问题的修补程序(在traceflag 4130下)。

a different connect item

中解释了性能退化的原因
  

由于一般的万圣节保护逻辑,引入了线轴   (XQuery表达式不需要这样做。)

答案 1 :(得分:6)

看起来是特定于SQL Server 2008的问题。当我在SQL Server 2005中运行代码时,两个插入都快速运行并生成相同的执行计划,从下面显示的片段开始为计划1 。 2008年,第一个插入使用计划1 ,但第二个插入生成计划2 。除了显示的片段之外,两个计划的其余部分都是相同的。

计划1

alt text

计划2

alt text