0

いくつかの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テーブル/列から取得されます。

このコードに関する私の質問は次のとおりです。

  1. この処理中に、他のエントリがresults.rawDataテーブルに絶えず追加される可能性があります。XMLノードから選択して一時テーブルを作成するのに少し時間がかかります。これが発生している間にテーブルに挿入しようとすると、強制的に待機する可能性があるのではないかと心配しています。手順の最初にある列を使用してresultId、手順が一度に機能するデータのスコープを作成しようとしています。

  2. この処理時間中に、他のテーブルを照会できます(コンピューターに存在するソフトウェアを見つけるなど)。これらのテーブルに短い一括挿入を1回だけ行うので、問題はないと思います。

  3. #TempSoftwareテーブルにはインデックスがなく、2つの列で結合しますNVARCHAR(MAX)。このテーブルにインデックスを作成する価値はありますか?または、インデックスを作成するオーバーヘッドは、結合よりも悪くなります。

  4. 私はここで愚かなことをしているのですか?

提案をありがとう。繰り返しますが、私はデータベースの大物ではありません。データベースですべての処理を直接実行する方が、生データをC#にプルバックし、処理を実行してデータベースに再挿入するよりも優れていると想定しています。

4

1 に答える 1

0

私のアプローチは、一時作業テーブルに挿入したデータにフラグを立てる追加の(日時)列を追加することです。一時作業テーブルを処理してからカムバックし、新しい行を確認します。これはかなり軽量である必要があります。必要に応じて、独自のトランザクションを実行する必要があります。

通常、インデックスなし=悪い、関連するインデックス=良い。常にクラスター化されたインデックスが必要ですが、データのランダム性に応じて、これを密にパックしたり、パディングしたりすることができます。80%が良い出発点です。行をコピーするオーバーヘッドが発生します。SQLはインデックスの作成に非常に優れているため、挿入してからインデックスを作成するのが最適な順序です。

この種の問題が再発すると思われる場合は、SSIShttp ://en.wikipedia.org/wiki/SQL_Server_Integration_Servicesを参照してください。MSのドキュメントが優れたGoogleと同じくらい役立つと期待しないでください。MSはそうではありません。この点でその場所を変更します。SSISはいつか理解する価値があります

于 2013-02-15T18:56:15.147 に答える