SQL 2005和SQL 2008之间的区别,用于使用XML插入多行

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标准版.

Mar*_*ith 8

这是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站点项中提到了各种其他解决方法.


jpi*_*son 2

顺便说一句,遇到此问题的其他人可能会发现SQLServerCentral 上的这篇文章有一定用处。查询的 x 路径部分的制定方式的细微差别似乎会对性能产生很大影响,具体取决于兼容性设置。

最初,我找不到关于为什么兼容性设置如此显着改变性能的大量解释,但从那时起,Martin Smith 的回答和Microsoft Connect 网站上报告的相应问题解释说,这可能是 SQL 2008 中的一个错误,并且有一个修补程序以及其他几个存在的解决方法,其中我在 SQLServerCentral 上的原始链接中的解决方法就是其中之一。

  • 这是一个已知的错误,详细信息请参阅我的答案。 (2认同)