【问题标题】:T-SQL Split Update Statement Into Parallel ChunksT-SQL 将更新语句拆分为并行块
【发布时间】:2013-10-08 21:07:23
【问题描述】:

我有一个在表格中构建树型结构的过程。然后,一旦构建了树,就会运行更新语句以根据表中的其他列(在过程的树创建部分期间创建的)更新表中的 1 列。所以更新中没有加入其他表。一切都可以在表格中逐行完成。表格示例(更新前)如下。

DrillPath    TimePeriod    CellValue
1            1             NULL
1,2          1             NULL
1,3          1             NULL
1            2             NULL
1,2          2             NULL
1,3          2             NULL

所以更新语句看起来像这样。

update table set CellValue = dbo.SomeLongRunningFunction(DrillPath, TimePeriod)

函数dbo.SomeLongRunningFunction() 每次调用运行大约 5 毫秒,我们调用它数十万次(这就是表中存在的行数)。过去大约需要 90 毫秒,因此我们已经大大提高了函数的性能。该函数本质上相当复杂,但我在此示例中抽象出复杂性。更新后的表格示例。

DrillPath    TimePeriod    CellValue
1            1             5.1
1,2          1             3.2
1,3          1             NULL (NULL can be a valid answer)
1            2             1.0
1,2          2             2.5
1,3          2             8.1

我想将此更新“分块”为 5 个(或在一般情况下 x 并行更新),每个更新对行的一个子集进行操作。 with (rowlock) 提示也许可以用来确保不会发生死锁,因为每个“块”都会更新它自己的行,而“块”永远不会相交。

我的第一个首选应用程序是 SSIS,它并行运行存储过程 5 次,并传入要更新的低/高范围。然而,似乎只有 1 个程序实际上在任何给定时间更新,而其他程序正在等待。这让我相信即使with (rowlock) 正在用于更新,更新语句也会锁定整个表。我知道只有 1 条正在运行,因为我可以从查询窗口中的表中选择并查看已更新的记录数。如果我将工作拆分到 5 个进程中,记录的数量并没有以我期望的速度增加。

我正在寻求有关如何并行运行这些更新的任何其他方法和建议。我需要在安全环境中保持在“开箱即用”SQL Server 2008 R2 企业版的范围内(没有 xp_cmdshell,如果没有其他选项,可能是 CLR 函数或自定义程序集)。我也可以选择 SSIS。

有什么想法吗?

【问题讨论】:

  • 您究竟是如何拆分更新的?你用了PK范围还是别的什么?
  • 我没有发现很多(如果有的话)封装在 UDF 中的逻辑不能基于集合的问题,那么如果可重用性是一个问题,则将其添加到视图中(所以您可以加入视图而不是执行函数)。我认为最好的解决方案是分离您的 UDF 并尝试更快地进行更新,而不是尝试一次进行更多更新。
  • 更新在 RowNumber 列上拆分,该列是 PK 的一部分。我有一个 proc 将行分成组(1-100、101-200、201-300 等),然后更新过程接受低和高范围,并且更新语句有一个 where 子句来限制记录.
  • 嗨 GarethD。我们尝试了基于集合的计算而不是函数,但没有成功。函数中的逻辑实在是太复杂了。我总是朝着基于集合的方法努力,但在这种情况下,UDF 是必需的。

标签: sql tsql ssis sql-server-2008-r2 parallel-processing


【解决方案1】:

所以我实际上决定在运行更新的过程中只使用一个表变量。

Step 1: insert into the table variable the "chunk" from the real table that I want to update.
Step 2: update the column in the table variable.
Step 3: delete the "chunk" from the real table.
Step 4: insert the table variable rows into the real table.

这消除了任何与锁定有关的问题,而且我的块还不够大,无法真正引起对内存利用率的任何担忧。

我能够在 SSIS 中并行运行该过程,并且发现运行时间与我使用的块数成正比。

【讨论】:

    猜你喜欢
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多