sql - 如何在线程中异步执行大量 sql 查询
问题描述
问题:我有大量的 sql 查询(大约 10k-20k),我想在 50 个(或更多)线程中异步运行它们。
我为这个工作写了一个powershell脚本,但是速度很慢(全部执行大约需要20个小时)。期望的结果是最多 3-4 小时。
问题:如何优化这个 powershell 脚本?我是否应该重新考虑并使用另一种技术,例如python
or c#
?
我认为这是 powershell 问题,因为当我检查whoisactive
查询时执行速度很快。创建、退出和卸载作业需要花费大量时间,因为每个线程都创建了单独的 PS 实例。
我的代码:
$NumberOfParallerThreads = 50;
$Arr_AllQueries = @('Exec [mystoredproc] @param1=1, @param2=2',
'Exec [mystoredproc] @param1=11, @param2=22',
'Exec [mystoredproc] @param1=111, @param2=222')
#Creating the batches
$counter = [pscustomobject] @{ Value = 0 };
$Batches_AllQueries = $Arr_AllQueries | Group-Object -Property {
[math]::Floor($counter.Value++ / $NumberOfParallerThreads)
};
forEach ($item in $Batches_AllQueries) {
$tmpBatch = $item.Group;
$tmpBatch | % {
$ScriptBlock = {
# accept the loop variable across the job-context barrier
param($query)
# Execute a command
Try
{
Write-Host "[processing '$query']"
$objConnection = New-Object System.Data.SqlClient.SqlConnection;
$objConnection.ConnectionString = 'Data Source=...';
$ObjCmd = New-Object System.Data.SqlClient.SqlCommand;
$ObjCmd.CommandText = $query;
$ObjCmd.Connection = $objConnection;
$ObjCmd.CommandTimeout = 0;
$objAdapter = New-Object System.Data.SqlClient.SqlDataAdapter;
$objAdapter.SelectCommand = $ObjCmd;
$objDataTable = New-Object System.Data.DataTable;
$objAdapter.Fill($objDataTable) | Out-Null;
$objConnection.Close();
$objConnection = $null;
}
Catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-Host "[Error processing: $($query)]" -BackgroundColor Red;
Write-Host $ErrorMessage
}
}
# pass the loop variable across the job-context barrier
Start-Job $ScriptBlock -ArgumentList $_ | Out-Null
}
# Wait for all to complete
While (Get-Job -State "Running") { Start-Sleep 2 }
# Display output from all jobs
Get-Job | Receive-Job | Out-Null
# Cleanup
Remove-Job *
}
更新:
资源:数据库服务器位于远程机器上:
- 24GB 内存,
- 8核,
- 500GB 存储空间,
- SQL 服务器 2016
我们要使用最大的 cpu 功率。
框架限制:唯一的限制是不使用 SQL Server执行查询。请求应来自外部来源,例如:Powershell、C#、Python 等。
解决方案
您需要重新组织脚本,以便在每个工作线程中保持数据库连接打开,并将其用于该线程执行的所有查询。现在,您正在为每个查询打开一个新的数据库连接,这会增加大量开销。消除这种开销应该可以加快速度达到或超过您的目标。
推荐阅读
- puppeteer - `page.goto` 超时后 Puppeteer `page` 对象不起作用?
- swift - NSTableView 逐行滚动
- android - 字段_user尚未初始化 - Flutter
- ios - 尝试从 Swift iOS 中的地图打开商店位置时,Google 地图永远加载
- grpc - 持久的 grpc 流式 RPC 和退避策略
- paypal - Paypal 订阅用户:50% 的时间显示“我们无法处理您的定期付款”
- sql - 当值更改时重置行号
- javascript - 为什么 npm run 会导致错误:“Router.use() 需要一个中间件函数,但需要一个 ' + gettype(fn)”?
- python - FastAI NLP 迁移学习,迁移学习模型是否具有预训练模型的词汇?
- flutter - 如何使用键组合两个嵌套映射的子集?