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. 在此处理时间内,可以查询其他表(例如找出计算机上存在哪些软件)。由于我只对这些表进行了一次简短的批量插入,因此我假设那里应该没有问题。

  3. #TempSoftware表没有索引,我对两NVARCHAR(MAX)列进行连接。是否值得在此表上创建索引?或者创建索引的开销会比连接更糟。

  4. 我在这里做了什么愚蠢的事,我应该被打吗?

感谢您的任何建议。同样,我不是一个大数据库人。我假设直接在数据库中进行所有处理比将原始数据拉回 C#、进行处理并重新插入数据库要好。

4

1 回答 1

0

我的方法是添加一个附加(日期时间)列来标记您已插入到临时工作表中的数据。处理临时工作表,然后返回以检查新行。这应该是相当轻量级的。如果需要,它应该在自己的事务中。

通常没有索引 = 坏,相关索引 = 好。您应该始终拥有一个聚集索引,但是这可以紧密打包或填充,具体取决于数据的随机性。80% 是一个很好的起点。Whist 您将获得复制行的开销。SQL 是非常好的一个创建索引,所以插入,然后创建索引是最好的顺序。

如果您认为此类问题会反复出现,您可能需要查看 SSIS http://en.wikipedia.org/wiki/SQL_Server_Integration_Services——不要指望 MS 文档会像好的 google 一样有用,MS 不会在这方面改变自己的立场。SSIS 值得在某个时候掌握

于 2013-02-15T18:56:15.147 回答