【问题标题】:How to execute in parallel using Transaction SQL?如何使用事务 SQL 并行执行?
【发布时间】:2014-07-17 14:29:14
【问题描述】:

我需要在计划的 SQL 代理作业中调用具有数百个不同参数的存储过程。现在它是按顺序执行的。我想同时执行具有 N 个(例如 N = 8)个不同参数的存储过程。

在Transaction SQL中实现它是不是一个好方法? SQL Server 服务代理可以用于此目的吗?还有其他选择吗?

【问题讨论】:

  • 您试图违反 SQL Server 事务的核心功能,即事务独立于其他事务。您对该 sp 的一次调用不应依赖于同一 sp 的任何其他调用。
  • 我只想并行执行一段不同参数的代码。给定不同的参数,过程访问完全不同的表。
  • 您是否尝试过再创建 7 个 SQL 代理作业并安排它们同时运行?我认为在这种情况下它们将彼此相距仅 1 秒。
  • @srutzky SP 的参数是从表中读取的。并且每次执行时间可能会有很大差异。我想通过动态调度来保持N个程序运行。

标签: sql-server sql-server-2008 service-broker


【解决方案1】:

评论中提到了一个表的问题,该表包含用于调用 proc 的各种参数,并且执行时间因参数值而异。

如果您能够在参数表中添加两个字段--StartTime DATETIMEEndTime DATETIME--那么您可以再创建 7 个 SQL 代理作业并安排它们同时运行。

每个Job的Job Step应该是一样的,并且应该类似如下:

DECLARE @Params TABLE (ParamID INT, Param1 DataType, Param2 DataType, ...);
DECLARE @ParamID INT,
        @Param1Variable DataType,
        @Param2Variable DataType,
        ...;

WHILE (1 = 1)
BEGIN
   UPDATE TOP (1) param
   SET    param.StartTime = GETDATE()  -- or GETUTCDATE()
   OUTPUT INSERTED.ParamID, INSERTED.Param1, INSERTED.Param2, ...
   INTO   @Params (ParamID, Param1, Param2, ...)
   FROM   Schema.ParameterTable param
   WHERE  param.StartTime IS NULL;

   IF (@@ROWCOUNT = 0)
   BEGIN
      BREAK; -- no rows left to process so just exit
   END;

   SELECT @ParamID = tmp.ParamID,
          @Param1Variable = tmp.Param1,
          @Param2Variable = tmp.Param2,
   FROM   @Params tmp;

   BEGIN TRY
      EXEC Schema.MyProc @Param1Variable, @Param2Variable, ... ;

      UPDATE param
      SET    param.EndTime = GETDATE() -- or GETUTCDATE()
      FROM   Schema.ParameterTable param
      WHERE  param.ParamID = @ParamID;
   END TRY
   BEGIN CATCH
      ... do something here...
   END CATCH;

   DELETE FROM @Params; // clear out last set of params
END;

该通用结构应允许 8 个 SQL 作业运行,直到所有参数值集都已执行。它解释了这样一个事实,即某些集合会比其他集合运行得更快,因为每个 Job 只会从队列中选择下一个可用的集合,直到没有剩余集合,此时 Job 将干净地退出。

要考虑添加到上述结构中的两件事:

  • 一种将 StartTime 字段重置为 NULL 以便稍后可以重新运行该行的方法
  • 一种处理错误的方法(即清理 StartTime 不是 NULL 并且 EndTime 是 NULL 并且 StartTime 和 GETDATE / GETUTCDATE 之间的 DATEDIFF 太多的行。TRY / CATCH 可以通过将 StartTime 设置回 NULL 来实现重新运行,或者为 ErrorTime DATETIME 添加第三个字段,该字段在运行开始时重置为 NULL(与其他 2 个字段一样),但仅在发生错误时设置。这些只是一些想法。

【讨论】:

  • 这可能是 SQL Server 中最简单的方法。
【解决方案2】:

SQL Server 没有内置任何东西来从 T-SQL 批处理发出并行查询。您需要一个外部驱动程序。连接 N 个连接的人。

如果您创建 N 个作业并手动启动它们,SQL 代理可以做到这一点。这是一个 hack,但它会起作用。

编写一个小型 C# 应用程序执行此操作并将其放入 Windows 任务计划程序可能更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 2013-06-01
    • 2018-06-02
    • 1970-01-01
    • 2016-05-21
    • 2018-05-03
    • 2011-03-22
    相关资源
    最近更新 更多