私はNOAAの現在の観測XML(例:ワシントンDC)を使用しており、4000以上のステーションのファイルをSQL Server2008R2テーブルに細断処理しています。多くの異なるアプローチを試した後、私は前進しているアプローチを持っています。
この質問は、さまざまな方法間のパフォーマンスに関するものであり、最も重要なのは、なぜそれがそれほど劇的なのかということです。
最初の試み
C#での作業では、Linq to XMLを使用してすべてのファイルを解析し、結果のレコードをLinqtoSQLを使用してデータベースに書き込みました。このためのコードは予測可能であるため、私はあなたを退屈させません。
linqを使用してEntityFrameworkに書き換えても効果はありませんでした。
その結果、アプリケーションは1時間以上実行され、1600程度のファイルしか処理されませんでした。速度が遅いのは、LinqtoSQLとLinqtoEntitiesの両方が、レコードごとに挿入と選択を実行した結果です。
2回目の試行
まだC#で作業しているので、オンラインで利用できる一括挿入メソッドを使用して高速化を試みました(例:Linq-to-SQLを使用した挿入の高速化-パート1)。
最初の試みよりも著しく速いが、それでも遅い。
この時点で、ストアドプロシージャを使用してXMLシュレッダーを処理し、ファイルを1つのXML文字列に連結してラッパータグを追加するC#コードを挿入するようになりました。
3回目の試行
これに似たSQLServerの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件程度のレコードを処理してキャンセルしました。
4回目の試行
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つを間違って使用していたことが示されてとてもうれしいです。