いくつかのXMLを処理し、それを複数のテーブルに正規化するデータベースプロシージャがあります。私は巨大なデータベースの人ではなく、データベースのロックについてほとんど知らないので、私がしていることが完全に間違っているかどうか疑問に思っています。
まずresults
、次のようなものを含むテーブルがあります。
resultId、computerId(int)| rawData(xml) ------------------------------- 1 | 1 | <installedSoftware> <software name = "Google Chrome" version = "1.0" /> <software name = "Mozilla Firefox" version = "3.0" /> </ installedSoftware> 2 | 2 | <installedSoftware> <software name = "Internet Explorer" version = "6" /> <software name = "Google Chrome" version = "1.0" /> </ installedSoftware>
私のストアドプロシージャは次のようになります。
CREATE TABLE #ResultsToProcess
(
int resultId
)
-- Only trying to process 1000 results at a time. If I try to do to many at once, I sometimes get timeouts. Instead I do small chunks.
SELECT
TOP 1000
resultId
FROM
results
CREATE TABLE #TempSoftware
(
computerId INT,
softwareName NVARCHAR(MAX),
softwareVersion NVARCHAR(MAX)
)
INSERT INTO #TempSoftware
SELECT DISTINCT
computerId,
T(N).value('(@name[1])', 'NVARCHAR(MAX)') AS softwareName,
T(N).value('(@version[1])', 'NVARCHAR(MAX)') AS softwareVersion,
FROM
results CROSS APPLY results.rawData.nodes('/installedSoftware[1]/software') AS T(N)
INNER JOIN #ResultsToProcess ON results.resultId = #ResultsToProcess.resultId
-- May need to do some additional processing on the temporary data before actually using it.
-- To reduce duplicate data, we insert into a full list of software. There is an index based on softwareName and softwareVersion. The softwareTable has an auto increment int primary key.
INSERT INTO software(softwareName,softwareVersion)
SELECT DISTINCT softwareName, softwareVersion FROM #TempSoftware
WHERE NOT EXISTS(SELECT 1 FROM software WHERE software.softwareName = #TempSoftware.softwareName AND software.softwareVersion = #TempSoftware.softwareVersion)
-- Finally we will link any software to the computer. However in this case, the temp table does not have any indexes. Would it be worth-while to add some?
INSERT INTO computer_software(computerId,softwareId)
SELECT
#TempSoftware.computerId,
#software.softwareId
FROM #TempSoftware INNER JOIN ON software ON #TempSoftware.softwareName = software.softwareName AND #TempSoftware.softwareVersion = #software.softwareVersion
したがって、これに加えて、プロシージャは他のコンピュータベースの属性も処理します。これらはすべて同じresults.rawData
テーブル/列から取得されます。
このコードに関する私の質問は次のとおりです。
この処理中に、他のエントリがresults.rawDataテーブルに絶えず追加される可能性があります。XMLノードから選択して一時テーブルを作成するのに少し時間がかかります。これが発生している間にテーブルに挿入しようとすると、強制的に待機する可能性があるのではないかと心配しています。手順の最初にある列を使用して
resultId
、手順が一度に機能するデータのスコープを作成しようとしています。この処理時間中に、他のテーブルを照会できます(コンピューターに存在するソフトウェアを見つけるなど)。これらのテーブルに短い一括挿入を1回だけ行うので、問題はないと思います。
#TempSoftware
テーブルにはインデックスがなく、2つの列で結合しますNVARCHAR(MAX)
。このテーブルにインデックスを作成する価値はありますか?または、インデックスを作成するオーバーヘッドは、結合よりも悪くなります。私はここで愚かなことをしているのですか?
提案をありがとう。繰り返しますが、私はデータベースの大物ではありません。データベースですべての処理を直接実行する方が、生データをC#にプルバックし、処理を実行してデータベースに再挿入するよりも優れていると想定しています。