【问题标题】:Running Stored Procedure multiple times concurrently同时运行存储过程多次
【发布时间】:2013-04-03 06:24:23
【问题描述】:

如何使用不同的参数值集多次运行相同的存储过程,而无需等待第一次执行完成。

例子:

如果我从@sourceId,@containerId 获得了proc sp_loaddata

Execution - 1st:  exec sp_loaddatafrom 100001, 36
Execution - 2nd:  exec sp_loaddatafrom 100008, 92
Execution - 3rd:  exec sp_loaddatafrom 100005, 112

我希望所有人同时运行。

如何在 T-SQL / SSIS / C# 中实现这一点

【问题讨论】:

  • 如果可能的话,最好修改存储过程以接受Table-valued parameter - 这样它就可以运行基于集合的查询来产生所有结果 - SQL Server 可以适当地优化这个过程。
  • 另外,您应该避免使用sp_ 作为存储过程的前缀。它仅供 Microsoft 使用,并且它具有内置的特殊(有时是不受欢迎的)行为(特别是,SQL Server 在搜索当前数据库之前总是会尝试在master 中找到此类过程 - 所以如果 MS 添加一个新的与您选择的名称冲突,将使用 MS 名称)
  • 另外我个人会使用 ORM,除非这个查询有副作用。
  • @Damien_The_Unbeliever 感谢您对 sp_ 的指点,是的,我知道这一点,但我不确定我是如何在我的问题中错过它的 :-)

标签: c# sql-server-2008 tsql ssis


【解决方案1】:

如果您可以访问 .net 4.5,我会使用以下代码。

var results = Task.WhenAll(
    Task.Run(() => RunStoredProc(1)),
    Task.Run(() => RunStoredProc(2)),
    Task.Run(() => RunStoredProc(3))
).Result;

如果我只有 .net 4.0,我会使用 TPL。稍微麻烦一点,还是比后台worker好很多。

var arguments = new []{1,2,3};

var results = from x in arguments.AsParallel()
              select RunStoredProc(x);

【讨论】:

    【解决方案2】:

    如果您将使用 C#,您可以使用 3 个 BackgroundWorkers 在其 Do_Work 事件中调用所述存储过程

    【讨论】:

    • 我只会使用 BackgroundWorkers IFF 我只能访问 .net
    【解决方案3】:

    这可以在 SSIS 中通过使用 3 个不同的 Execute SQL Task 来完成,它们彼此没有连接。

    默认情况下,SSIS 对Isolation Level 使用Serializable 选项,该选项锁定正在读取的整个数据并保持锁定直到事务完成。因此,为了并行运行查询,您需要将Isolation level 更改为Snapshot,它在读取数据时基本上使用NOLOCK

    更新:-

    由于获取到的stored procedures被执行的数量是dynamically,那么你需要创建包programitically

    public void CreatePackage()
    {
      Package package= new Package();
      ConnectionManager sqlConnection = GetSQLConnection(package,
                                        "localhost", "Database Name");
      TaskHost taskHost=null;
       for(int i=0;i<GetNoOfRowFromSQL();i++)
        {
          CreateDynamicTask(package);
        }
      package.Execute();
    }
    
    public void CreateDynamicTask(package Package)
    {
    
          //Add the Execute SQL Task
          package.Executables.Add("STOCK:SQLTask");
           taskHost = package.Executables[0] as TaskHost;
          taskHost.Properties["SqlStatementSource"].SetValue(taskHost, 
                                                "EXECUTE Stored Proc);
         //Setting the Isolation Level
         taskHost.Properties["IsolationLevel"].SetValue(taskHost, 1048576);
         //the number signify 1048576 =Serializable
        }
    }
    

    【讨论】:

    • 这总是不只是三次调用程序;我的参数值来自表和编号。要执行的存储过程的时间取决于参数值表中的行数。
    • 但我更喜欢使用 TPLSystem.Threading.Tasks.Parallel.Invoke(() =&gt; { CallSP1(); }, () =&gt; { CallSP12(); }, () =&gt; { CallSP3(); } );,而不是陷入使用 C# 创建 SSIS 包的麻烦
    猜你喜欢
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    相关资源
    最近更新 更多