按顺序或并行启动存储过程

时间:2008-12-08 15:58:54

标签: sql sql-server tsql sql-server-2000 parallel-processing

我们有一个每晚运行的存储过程,然后启动许多其他过程。其中一些程序在逻辑上可以与其他一些程序并行运行。

  • 如何向SQL Server指示程序是应该并行还是串行运行 - 即:异步启动还是阻塞?
  • 并行运行它们的意义是什么,请记住我已经确定进程不会竞争表访问或锁定 - 只是总磁盘io和内存。在大多数情况下,他们甚至不使用相同的表格。
  • 如果其中一些程序是相同的程序,只是使用不同的参数,这是否重要?
  • 如果我异步启动一对或多个程序,SQL Server中是否有一个好的系统等待它们两个完成,或者我是否需要让它们每个都在某个地方设置一个标志并定期检查和轮询该标志使用WAITFOR DELAY

目前我们还在SQL Server 2000上。

作为旁注,这很重要,因为主程序是响应从大型机系统完成从服务器到服务器的数据而启动的。大型机转储每晚大约需要2个小时,我们无法控制它。因此,我们一直在努力寻找缩短处理时间的方法。

4 个答案:

答案 0 :(得分:12)

我最近不得不对此进行研究,因此发现这个老问题正在寻求更完整的答案。只是完全明确: TSQL (单独)能够异步启动其他TSQL操作

这并不意味着你仍然没有很多选择(其中一些在其他答案中提及):

  • 自定义应用程序:使用异步方法,以您选择的语言编写一个简单的自定义应用程序。在每个应用程序线程上调用SQL存储过程。
  • SQL代理作业:创建多个SQL作业,并使用sp_start_job从您的proc异步启动它们。您可以检查他们是否已完成使用Gregory A. Larsen在this excellent article中所述的未记录的函数xp_sqlagent_enum_jobs。 (或者让作业本身更新你自己的JOB_PROGRESS表,正如克里斯所建议的那样。)你真的必须为你预期运行的每个并行进程创建单独的作业,即使它们使用不同的参数运行相同的存储过程。
  • OLE自动化:使用sp_oacreatesp_oamethod启动一个新进程,调用另一个存储过程,如this article中所述,也由Gregory A. Larsen执行
  • DTS包:使用简单的分支任务流创建DTS或SSIS包。 DTS将以单独的spid启动任务。
  • Service Broker :如果您使用的是SQL2005 +,请查看使用Service Broker
  • CLR并行执行:使用CLR命令Parallel_AddSqlParallel_Execute,如Alan Kaplan在this article中所述(仅限SQL2005 +)。
  • 计划的Windows任务:已列出完整性,但我不是此选项的粉丝。

我对Service Broker或CLR没有太多经验,因此我无法对这些选项发表评论。如果是我,我可能会在更简单的场景中使用多个作业,而在更复杂的场景中使用DTS / SSIS包。

最后一条评论:只要能够*,SQL就会尝试并行化各个操作。这意味着同时运行2个任务而不是相互运行并不能保证它会更快完成。仔细测试,看它是否真的改善了。

我们有一个开发人员创建了一个DTS包,可以同时运行8个任务。不幸的是,它只是一个4 CPU服务器:)

*假设默认设置。这可以通过更改服务器的最大并行度或亲和力掩码,或使用MAXDOP查询提示进行修改。

答案 1 :(得分:3)

创建几个SQL Server代理作业,其中每个作业都运行特定的proc。

然后从你的主人内部开始工作。

我能想到的唯一等待方式是,如果你有一个状态表,每个proc都会在完成时更新。

然后另一个工作可以轮询该表以完成完成并启动最终的过程。或者,您可以在此表上触发。

内存含义完全取决于您的环境..

<强>更新 如果您可以访问任务系统..那么您可以采用相同的方法。只需让windows执行多个任务,每个任务负责一个proc。然后在状态表上使用触发器,在所有任务完成后启动。

<强> UPDATE2: 此外,如果您愿意创建一个新的应用程序,您可以将所有逻辑放在一个exe ...

答案 2 :(得分:2)

你需要将过夜的活动转移到工作岗位上。 SQL Server作业控制将允许您执行所需的所有计划。

答案 3 :(得分:2)

您可能希望研究使用DTS(可以从SQL Agent作为作业运行)。它将允许您非常精细地控制哪些存储过程需要等待其他人完成以及可以并行运行的内容。如果需要,您还可以从自己的计划软件中将DTS包作为EXE运行。

注意:您需要创建连接对象的多个副本,以允许并行运行调用。即使您没有明确地放入依赖项,使用相同连接对象的两个调用仍然会相互阻塞。