代码之家  ›  专栏  ›  技术社区  ›  Jeff Meatball Yang

如何异步调度数千个SQL请求

  •  1
  • Jeff Meatball Yang  · 技术社区  · 14 年前

    • 构建数以千计的SQL select语句
    • 使用BeginExecuteReader运行每个选择

    我们是:

    • 在回调处理程序中调用EndExecuteReader。
    • 递归地启动另一个调用

    public static void StartQuery() {
      // build the query for array[i]
      // ...
      SqlConnection conn = new SqlConnection(AsyncConnectionString);
      conn.Open();
      cmd.BeginExecuteReader(CallbackHandler, cmd);
    
      i++;
    }
    
    
    
    public static void CallbackHandler(IAsyncResult ar) {
         // unpack the cmd
         cmd.EndExecuteReader();
    
         // read some stuff to a DataTable...
    
         // SqlBulkCopy to another database (synchronously)
    
         cmd.Connection.Close();
         cmd.Connection.Dispose();
    
         StartQuery();
     }
    

    谢谢!

    1 回复  |  直到 14 年前
        1
  •  4
  •   Remus Rusanu    14 年前

    我想你确实设置了 AsyncronousProcessing

    • 你很快就会被 max worker threads Open 时间和频繁的超时。
    • 并行运行1000个负载比在N个连接上顺序运行1000个负载要慢得多,其中N是由服务器上的内核数给定的。数千个并行请求只会在共享资源上造成过度争用,并使彼此速度减慢。
    • 在CLR中排队的数千个请求绝对不可靠。如果程序崩溃,你就失去了所有的工作 去掉任何痕迹

    一种更好的方法是使用一个队列,从该队列中加载和执行一组工作线程。典型的生产者消费者。worker(consumer)的数量将由SQL Server资源(CPU核心、内存、负载的IO模式)进行调整,但安全的数量是服务器核心数量的2倍。每个工人都使用一个专用连接来完成其工作。工人的角色和排队的角色不是为了加快工作速度,相反,他们扮演着 节流 防止服务器崩溃的机制。

    一种更好的方法是将队列持久化到数据库中,作为从崩溃中恢复的一种方法。见 Using Tables as Queues 因为基于表的队列是出了名的容易出错的。

    最后,您可以让SQL Server通过 Activation Asynchronous Procedure Execution 以及后续文章 Passing Parameters to a Background Procedure

    哪一个是正确的解决方案取决于你对你的问题了解的许多因素,但我不知道,所以我不能建议你应该走哪条路。