Sam*_*han 7 xml sql-server-2005 sql-server-2008
可能重复:
为什么从XML变量中插入 - 选择变量表这么慢?
我使用以下SQL代码在表中插入多行数据.使用XML变量将数据传递给存储过程:
INSERT INTO MyTable
SELECT SampleTime = T.Item.value('SampleTime[1]', 'datetime'),
Volume1 = T.Item.value('Volume1[1]', 'float'),
Volume2 = T.Item.value('Volume2[1]', 'float')
FROM @xml.nodes('//Root/MyRecord') T(item)
Run Code Online (Sandbox Code Playgroud)
我有一大堆单元测试来验证我正在插入正确的信息,正确的记录数等等.当我调用存储过程时.
所有罚款和花花公子 - 也就是说,直到我们开始使用数据库的兼容级别.
只要我们将DB的兼容级别保持在90(SQL 2005),上面的代码就可以很好地工作.当我们将兼容级别设置为100(SQL 2008)时,单元测试失败,因为使用上面代码的存储过程超时.
单元测试正在丢弃数据库,从脚本重新创建数据库,并在全新的数据库上运行测试,所以它不是 - 我认为 - 一个关于"旧兼容性级别"的问题.
使用SQL Management工作室,我编写了一个快速测试SQL脚本.使用相同的XML块,我改变DB compat级别,截断表,然后使用上面的代码插入650行.当级别为90(SQL 2005)时,它以毫秒为单位运行.当级别为100(SQL 2008)时,它有时需要一分钟,有时会以毫秒为单位运行.
我很欣赏任何人可能对此有任何见解.
该脚本需要一分钟才能运行我的实际数据,这些数据的行数比我在此处显示的数量多,是一个真实的表,并且有一个索引.使用以下示例代码,差异介于毫秒和大约5秒之间.
--use [master]
--ALTER DATABASE MyDB SET compatibility_level =100
use [MyDB]
declare @xml xml
set @xml = '<?xml version="1.0"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Record>
<SampleTime>2009-01-24T00:00:00</SampleTime>
<Volume1>0</Volume1>
<Volume2>0</Volume2>
</Record>
..... 653 records, sample time spaced out 4 hours ........
</Root>'
DECLARE @myTable TABLE(
ID int IDENTITY(1,1) NOT NULL,
[SampleTime] [datetime] NOT NULL,
[Volume1] [float] NULL,
[Volume2] [float] NULL)
INSERT INTO @myTable
select
T.Item.value('SampleTime[1]', 'datetime') as SampleTime,
Volume1 = T.Item.value('Volume1[1]', 'float'),
Volume2 = T.Item.value('Volume2[1]', 'float')
FROM @xml.nodes('//Root/Record') T(item)
Run Code Online (Sandbox Code Playgroud)
我取消注释顶部的2行,选择它们并运行它(ALTER DATABASE语句),然后注释2行,取消选择任何文本并运行整个事情.
当我从90更改为100时,它会在5秒内一直运行(我更改了一次级别,但我会多次运行该系列以查看是否有一致的结果).当我从100更改为90时,它始终以毫秒为单位运行.这样你也可以玩它.我使用的是SQL Server 2008 R2标准版.
这是SQL Server 2008中的一个错误.
可以通过启用TraceFlag 4130来修复它,因为此repro显示.
USE [MyDB]
--Comment / Uncomment the next two lines as appropriate to test the effect with the TF turned on or off
DBCC TRACEON(4130,-1)
--DBCC TRACEOFF(4130,-1)
GO
DBCC FREEPROCCACHE
GO
declare @xmlstring varchar(max) = '<?xml version="1.0"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">'
SELECT @xmlstring +=
'<Record>
<SampleTime>2009-01-24T00:00:00</SampleTime>
<Volume1>0</Volume1>
<Volume2>0</Volume2>
</Record>'
FROM master..spt_values
WHERE type='P' AND number BETWEEN 1 AND 653
set @xmlstring += '</Root>'
DECLARE @xml xml = @xmlstring
SELECT @xml
DECLARE @myTable TABLE(
ID int IDENTITY(1,1) NOT NULL,
[SampleTime] [datetime] NOT NULL,
[Volume1] [float] NULL,
[Volume2] [float] NULL)
INSERT INTO @myTable
select
T.item.value('SampleTime[1]', 'datetime') as SampleTime,
Volume1 = T.item.value('Volume1[1]', 'float'),
Volume2 = T.item.value('Volume2[1]', 'float')
FROM @xml.nodes('//Root/Record') T(item)
Run Code Online (Sandbox Code Playgroud)
相关的Microsoft Connect站点项中提到了各种其他解决方法.
顺便说一句,遇到此问题的其他人可能会发现SQLServerCentral 上的这篇文章有一定用处。查询的 x 路径部分的制定方式的细微差别似乎会对性能产生很大影响,具体取决于兼容性设置。
最初,我找不到关于为什么兼容性设置如此显着改变性能的大量解释,但从那时起,Martin Smith 的回答和Microsoft Connect 网站上报告的相应问题解释说,这可能是 SQL 2008 中的一个错误,并且有一个修补程序以及其他几个存在的解决方法,其中我在 SQLServerCentral 上的原始链接中的解决方法就是其中之一。