【发布时间】: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