Проблема: У меня огромное количество SQL-запросов (около 10–20 тыс.), И я хочу выполнить их асинхронно в 50 (или более) потоках.
Я написал сценарий powershell для этой работы, но он очень медленный (на выполнение всех ушло около 20 часов). Желаемый результат - максимум 3-4 часа.
Вопрос: Как я могу оптимизировать этот скрипт powershell? Должен ли я пересмотреть и использовать другую технологию, такую как python
или 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 *
}
UPDATE:
Ресурсы: Сервер БД находится на удаленном компьютере с:
- 24 ГБ ОЗУ,
- 8 ядер,
- 500 ГБ,
- SQL Server 2016
Мы хотим использовать максимальную мощность процессора.
Основное ограничение: Единственное ограничение - не использовать SQL Server для выполнения запросов. Запросы должны поступать из внешних источников, таких как: Powershell, С#, Python и т.д.