SQL Server XML粉碎性能

时间:2012-07-15 00:59:24

标签: xml performance sql-server-2008-r2

我正在使用NOAA当前的观察XML(例如:Washington DC),并将4000多个站点的文件粉碎成SQL Server 2008 R2表。在尝试了许多不同的方法后,我有一个我正在前进的方法。

这个问题是关于不同方法之间的表现,最重要的是为什么它如此激烈。

首次尝试

使用C#解析所有使用Linq到XML的文件,并使用Linq to SQL将结果记录写入数据库。这个代码是可以预测的,所以我不会厌烦你。

使用linq重写实体框架没有帮助。

这导致应用程序运行了一个多小时,并且只处理了1600个左右的文件。缓慢是Linq to SQL和Linq to Entities执行插入并为每条记录选择的结果。

第二次尝试

仍在使用C#我尝试使用在线提供的批量插入方法加快速度(例如:Speeding up inserts using Linq-to-SQL - Part 1)。

仍然很慢,虽然明显快于第一次尝试。

此时我转向使用存储过程来处理XML碎化,并使用C#代码插入文件到一个XML字符串并添加包装器标记。

第三次尝试

使用类似于此的SQL Server XML查询(@xml是xml文件)[来自内存]:

select credit = T.observation.value('credit[1]', 'varchar(256)')
       ,... -- the rest of the elements possible in the file.
from @xml.nodes('wrapper') W(station)
    cross apply W.station.nodes('current_observation') T(observation)

我让它运行15分钟并取消处理250条左右的记录。

第四次尝试

我将查询更改为使用OpenXML:

declare $idoc int

exec sp_xml_preparedocument @idoc output, @xml

select Credit
       ,... -- the rest of the elements
from openxml(@idoc, '/wrapper/current_observations', 2)
    with (
        Credit varchar(256) 'credit'
        ,...) -- the rest of the elements

exec sp_xml_removedocument @idoc

这在10秒内处理了所有4000多条记录!非常接受。

虽然我预计这些方法之间存在一些差异,但我并不认为这种差异会如此显着。

所以我的问题很简单,

'为什么不同方法之间的表现有如此显着的差异?'

我很高兴被证明我使用的是前3个错误。

3 个答案:

答案 0 :(得分:2)

可能能够加快XQuery选项的一件事是避免交叉连接。

我看不出你的XML是什么样的 - 华盛顿特区的样本只包含一个节点 - 但假设XML只包含一个<wrapper>,然后在其中包含一个<current_observation>列表,那么你可以优化你的XQuery来阅读:

select 
    credit = T.observation.value('credit[1]', 'varchar(256)')
    ,... -- the rest of the elements possible in the file.
from 
    @xml.nodes('wrapper/current_observation') T(observation)

这应该比你在测试中看到的速度快很多。

如果你有时间尝试这个 - 我最感兴趣的是知道这种修改后的方法是如何叠加的 - 针对你原来的XQUery和OPENXML解决方案。

答案 1 :(得分:1)

您可以确认在查询中没有使用父轴('..')吗?这可能会破坏性能。您还可以添加text()访问器,这也应该提高性能,如下所示:

select
o.c.value('(credit/text())[1]', 'varchar(max)'),
--...
from @xml.nodes('wrapper/current_observation') o(c)

答案 2 :(得分:0)

您是否尝试过文本存取器?我的repro对一个包含4,096条记录的6MB xml文件有15-20%的改进,尽管这只适用于非类型化的XML(在SQL Server中没有关联的XSD)。

我还发现我的查询在10-12秒内运行,所以你的43秒仍然有些神秘。您使用的SQL Server版本/服务包是什么?我记得在插入表变量时,SQL 2005中曾经存在一个问题,但认为这是固定的。