Answers:
有一次,我在StackOverflow上回答了这个问题,但是在DBA.SE上进行修改和更新似乎也很有用。
只是为了完全明确:TSQL确实不(本身)具有异步启动其他TSQL操作的能力。
这并不意味着您仍然没有很多选择(其他答案中提到了其中一些):
sp_start_job
。如果您需要以编程方式监视其进度,只需确保每个作业都更新一个自定义的JOB_PROGRESS表即可(或者您可以xp_sqlagent_enum_jobs
按照Gregory A. Larsen的这篇出色文章中的说明,检查它们是否已经使用了未记录的功能)。您必须根据要运行的并行进程创建尽可能多的单独作业,即使它们正在运行具有不同参数的相同存储过程。sp_oacreate
和sp_oamethod
启动一个新进程,以互相调用存储的proc,如本文所述,Gregory A. Larsen也是如此。Parallel_AddSql
,Parallel_Execute
如Alan Kaplan 在本文中所述(仅适用于SQL2005 +)。如果是我,则可能会在较简单的方案中使用多个SQL Agent Job,而在较复杂的方案中使用SSIS软件包。
就您而言,除非您尝试启动200个单独的线程,否则多个计划的Agent作业听起来像是一个简单且易于管理的选择。
最后一条评论:SQL已经尝试在可能的情况下并行化各个操作*。这意味着不能同时运行两个任务,而不能同时运行两个任务,这不能保证它会更快地完成。仔细测试以查看它是否真的可以改善任何东西。
我们有一个开发人员创建了一个DTS包,以同时运行8个任务。不幸的是,它只是一个4-CPU服务器:)
*假设为默认设置。可以通过更改服务器的“最大并行度”或“相似性掩码”或使用MAXDOP查询提示来进行修改。
您可以使用Powershell。假设您正在使用SQL Server,则可以执行以下操作:(现在经过测试和清理)
#This script creates a number of connections (one per entry in $Commands)
# to a SQL Server instance ($Server) and database ($DBName)
#Driver variables
#Set Initial collections and objects
$Server= "(local)\sql2016cs" ; #Server to connect to
$DBName = "Test" ; #Database to connect to
$Commands = @()
$Commands += "EXEC sp_LogMe 'a'"
$Commands += "EXEC sp_LogMe 'b'"
#Loop through commands array, create script block for establishing SMO connection/query
#Start-Job for each script block
foreach ($sql in $Commands ) {
# All of that extra information after "Smo" tells it to load just v12 (for when you have multiple
# versions of SQL installed.) Note: V13 is 2016.
$cmdstr =@"
`Add-Type -AssemblyName "Microsoft.SqlServer.Smo,Version=$(13).0.0.0,Culture=neutral,PublicKeyToken=89845dcd8080cc91"
`[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
`$SqlConn = New-Object Microsoft.SqlServer.Management.Smo.Server ("$Server")
`$SqlConn.Databases["$DBName"].ExecuteNonQuery("$sql")
"@
#Uncomment the next like to print the command string for debugging
# $cmdstr
#Execute script block in jobs to run the command asyncronously
$cmd = [ScriptBlock]::Create($cmdstr)
Start-Job -ScriptBlock $cmd
}
注意:我从这里经过测试的类似内容中获取了此信息:https : //sqlstudies.com/2016/02/24/powershell-script-to-create-multiple-sql-server-connections/
在那个我正在运行一个循环,以创建一堆执行相同操作的命令。该脚本使用脚本块异步运行每个命令,但使用不同的实际命令。为了简化操作,我将要运行的命令列表放入数组中并遍历该数组。
我使用带有多线程的C#应用程序Parallel.ForEach
来调用具有不同参数的sp。分为三个部分。Init,Body,local最后
public void NearLinkParallelGeneration(avl_range avl_pending, DateTime dt_start_process)
{
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount + 2
};
// create the partition based on the input
var partitions = Partitioner
.Create(
fromInclusive: avl_pending.begin,
toExclusive: avl_pending.end,
rangeSize: 100
)
.GetDynamicPartitions();
Parallel.ForEach(
source: partitions,
parallelOptions: parallelOptions,
localInit: () =>
{
NpgsqlConnection conn = new NpgsqlConnection(strConnection);
NpgsqlCommand cmd = new NpgsqlCommand();
try
{
conn.Open();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM avl_db.process_near_link(@begin, @end, @start_time);";
cmd.CommandType = CommandType.Text;
NpgsqlParameter p = new NpgsqlParameter("@begin", NpgsqlDbType.Bigint);
cmd.Parameters.Add(p);
p = new NpgsqlParameter("@end", NpgsqlDbType.Bigint);
cmd.Parameters.Add(p);
p = new NpgsqlParameter("@start_time", NpgsqlDbType.Timestamp);
p.Value = dt_start_process;
cmd.Parameters.Add(p);
}
catch (NpgsqlException ex)
{
Console.WriteLine(ex.InnerException);
}
catch (System.Exception ex)
{
Console.WriteLine(ex.InnerException);
}
return new { Connection = conn, Command = cmd };
},
body: (source, state, local) =>
{
if (local.Connection.State == ConnectionState.Open)
{
string strResult = String.Format("From: {0} - To: {1}", source.Item1, source.Item2);
Console.WriteLine(strResult);
try
{
local.Command.Parameters["@begin"].Value = source.Item1;
local.Command.Parameters["@end"].Value = source.Item2;
local.Command.ExecuteNonQuery();
}
catch (NpgsqlException ex)
{
Console.WriteLine(ex.InnerException);
}
catch (System.Exception ex)
{
Console.WriteLine(ex.InnerException);
}
//strResult = String.Format("DONE From: {0} - To: {1}", source.Item1, source.Item2);
//Console.WriteLine(strResult);
}
return local;
},
localFinally: local =>
{
local.Command?.Dispose();
local.Connection?.Dispose();
}
);
}
您也可以ForEach -Parallel
在Powershell中使用。
下面的示例(摘自我的问题Powershell在数据库中并行运行存储过程 )将在数据库中运行所有存储过程:
Workflow TestRunParallelExecute
{
$ServerName = "localhost"
$DatabaseName = "testrun"
$Procedure_Query = "select name from sys.procedures"
$Procedure_List = (Invoke-Sqlcmd -Server $ServerName -Database $DatabaseName -Query $Procedure_Query)
ForEach -Parallel ($Procedure in $Procedure_List.Name)
{
Invoke-Sqlcmd -Server $ServerName -Database $DatabaseName -Query $Procedure
}
}
TestRunParallelExecute
cls