2012-07-15 60 views
5

我正在使用NOAA的當前觀察XML(例如:Washington DC),並將4000多個工作站的文件粉碎成SQL Server 2008 R2表。在嘗試了許多不同的方法之後,我有一個我正在前進的方法。SQL Server XML粉碎性能

這個問題是關於不同方法之間的表現,最重要的是它爲什麼如此激烈。

第一次嘗試

工作在C#我分析的所有文件的LINQ to XML和使用LINQ寫的結果記錄到數據庫SQL。這個代碼是可以預測的,所以我不會讓你感到厭煩。

用linq重寫實體框架沒有幫助。

這導致應用程序運行超過一個小時,並且只處理了大約1600個文件。緩慢是Linq to SQL和Linq to Entities對每條記錄執行插入和選擇的結果。

第二次嘗試

在C#中仍在工作,我試圖通過使用批量插入方法可在網上(例如:Speeding up inserts using Linq-to-SQL - Part 1),以加快速度。

仍然很慢,雖然比第一次嘗試速度更快。

在這一點上,我轉向使用存儲過程來處理XML碎化,並用C#代碼插入,將這些文件連接成一個XML字符串並添加包裝標記。

第三次嘗試

使用類似這樣(@xml是XML文件)從內存] SQL Server的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 

該處理的所有4000+記錄10秒!相當可以接受。

雖然我預計這些方法之間會有一些差異,但我並沒有預料到這種差異如此顯着。

所以我的問題很簡單,

「爲什麼會出現在不同的方法之間的性能這麼大的差別?

我很高興能夠證明我使用的是前3個錯誤。

回答

2

有一件事你可能能夠做到加快XQuery選項是爲了避免交叉連接。

我看不到你的XML是什麼樣的 - 華盛頓DC樣本只包含一個節點 - 但假設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解決方案。

+0

是的,我從每個文件拉current_observation節點,並將它們與圍繞它們很多的元素連接起來。 – 2012-07-15 18:22:36

+1

我以爲我曾嘗試引用current_observation標記沒有交叉應用,但顯然不是。我重新用你所建議的改變進行測試,並且如你所料,時間要快得多。處理4000+個current_observation元素需要43秒。儘管它仍然需要4倍的時間,但它在同一個地區,並解釋了爲什麼之前的差異如此激烈。 – 2012-07-15 18:32:54

+0

@DavidCulp:很好,謝謝你的反饋!有用的信息 – 2012-07-15 20:00:36

1

你能否確認你在查詢中沒有使用父軸('..')?這可能會破壞性能。您還可以添加文本()訪問器,這也應該提高性能,如下所示:

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

我沒有使用父軸。 – 2012-07-16 00:37:38

0

您是否嘗試過文本訪問器?雖然這隻適用於非類型化的XML(在SQL Server中沒有關聯XSD),但我的重新生成對6MB xml文件有4,096條記錄,但得到了15-20%的提升。

我也發現我的查詢在10-12秒內運行,所以我仍然有點神祕43秒。您使用的是哪種SQL Server版本/服務包?我記得在插入到表變量中時,SQL 2005中曾經存在過一個問題,但是認爲這是固定的。