Изменить сценарий PowerShell с Invoke на массовое копирование - PullRequest
0 голосов
/ 20 сентября 2019

Некоторое время я использовал приведенный ниже код, в основном в качестве теста, чтобы понять его немного подробнее.То, что я действительно хотел бы сделать сейчас, это улучшить его скорость с помощью массового копирования.

Код получает информацию о базе данных и таблице из серии экземпляров, которые хранятся в текстовом файле на сервере, затем добавляет собранные данные посредством вызова в таблицу.

Проблема заключается в том, чтоон отправляет данные для каждой базы данных и каждой таблицы по одному, если это вообще возможно.

Я просмотрел несколько сайтов / блогов, которые предоставляют информацию по этому вопросу, но все они, похоже, неименно то, что мне нужно.

$Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
$today = Get-Date
$srvlist = @(Get-Content "c:\scripts\tablegrowth.TXT")
foreach ($server in $srvlist) {
    $srv = New-Object "Microsoft.SqlServer.Management.SMO.Server" $server
    $dbs = $srv.Databases
    foreach ($db in $dbs) {
        if ($db.IsAccessible) {
            $name1 = $db.name
            $size1 = $db.size
            $dbspace1 = $db.DataSpaceUsage/1KB
            $dbindexsp1 = $db.IndexSpaceUsage/1KB
            $dbspaceavail1 = $db.SpaceAvailable/1KB
            #Write-Host "dbname=" $name1 $size1 $dbspace1 $dbindexsp1 $dbspaceavail1 $db.IsAccessible
            switch ($name1) {
                'master' {}
                'msdb' {}
                'model'  {}
                'SSISDB'  {}
                'SSRSData'  {}
                'Northwind' {}
                'tempdb' {}
                default {
                    Invoke-Sqlcmd -ServerInstance "******" -Database "DBAMonitoring" -Query "INSERT INTO is_sql_databases VALUES ('$server','$name1','$today',$dbspace1,$dbspaceavail1,$dbindexsp1) "
                    foreach ( $tbl in $db.tables) {
                        $tname1    = $tbl.Name
                        $tindexsp1 = $tbl.IndexSpaceUsed/1KB
                        $trows1    = $tbl.RowCount
                        $tspace1   = $tbl.DataSpaceUsed/1KB
                        #Write-Host "tbl name=" $tname1 $tindexsp1 $trows $tspace1
                        if ($trows1 -gt 500) {
                            Invoke-Sqlcmd -ServerInstance "****" -Database "DBAMonitoring" -    Query "INSERT INTO is_sql_tables VALUES ('$server','$name1','$tname1','$today',$trows1,$tspace1,$tindexsp1) "
                        } ####end RowCount > 0
                    } #####end Row loop
                } ###### end Default
            } #####end switch
        }  #####end IsAccessible
    }  #####end database loop
} ###end server loop

$Stopwatch.Stop()
$Stopwatch.Elapsed.TotalSeconds
$Stopwatch.Elapsed.TotalMinutes

1 Ответ

0 голосов
/ 20 сентября 2019

Один из способов - загрузить строки в DataTable и использовать .NET SqlBulkCopy непосредственно в сценарии для массовой вставки.Просто измените имена столбцов DataTable и типы данных в приведенном ниже примере, чтобы они соответствовали фактической таблице.

$dt = New-Object System.Data.DataTable;
[void]($dt.Columns.Add("server_name", [System.Type]::GetType("System.String")).MaxLength = 128)
[void]($dt.Columns.Add("name1", [System.Type]::GetType("System.String")).MaxLength = 128)
[void]($dt.Columns.Add("tname1", [System.Type]::GetType("System.String")).MaxLength = 128)
[void]($dt.Columns.Add("today", [System.Type]::GetType("System.DateTime")))
[void]($dt.Columns.Add("trows1", [System.Type]::GetType("System.Int64")))
[void]($dt.Columns.Add("tspace1", [System.Type]::GetType("System.Int64")))
[void]($dt.Columns.Add("tindexsp1", [System.Type]::GetType("System.Int64")))

$Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
$today = Get-Date
$srvlist = @(Get-Content "c:\scripts\tablegrowth.TXT")
foreach ($server in $srvlist) {
    $srv = New-Object "Microsoft.SqlServer.Management.SMO.Server" $server
    $dbs = $srv.Databases
    foreach ($db in $dbs) {
        if ($db.IsAccessible) {
            $name1 = $db.name
            $size1 = $db.size
            $dbspace1 = $db.DataSpaceUsage/1KB
            $dbindexsp1 = $db.IndexSpaceUsage/1KB
            $dbspaceavail1 = $db.SpaceAvailable/1KB
            #Write-Host "dbname=" $name1 $size1 $dbspace1 $dbindexsp1 $dbspaceavail1 $db.IsAccessible
            switch ($name1) {
                'master' {}
                'msdb' {}
                'model'  {}
                'SSISDB'  {}
                'SSRSData'  {}
                'Northwind' {}
                'tempdb' {}
                default {
                    # Invoke-Sqlcmd -ServerInstance "******" -Database "DBAMonitoring" -Query "INSERT INTO is_sql_databases VALUES ('$server','$name1','$today',$dbspace1,$dbspaceavail1,$dbindexsp1) "
                    foreach ( $tbl in $db.tables) {
                        $tname1    = $tbl.Name
                        $tindexsp1 = $tbl.IndexSpaceUsed/1KB
                        $trows1    = $tbl.RowCount
                        $tspace1   = $tbl.DataSpaceUsed/1KB
                        #Write-Host "tbl name=" $tname1 $tindexsp1 $trows $tspace1
                        if ($trows1 -gt 500) {
                            # Invoke-Sqlcmd -ServerInstance "." -Database "tempdb" -Query "INSERT INTO is_sql_tables VALUES ('$server','$name1','$tname1','$today',$trows1,$tspace1,$tindexsp1) "
                            $row = $dt.NewRow()
                            $dt.Rows.Add($row)
                            $row["server_name"] = $server
                            $row["name1"] = $name1
                            $row["tname1"] = $tname1
                            $row["today"] = $today
                            $row["trows1"] = $trows1
                            $row["tindexsp1"] = $tindexsp1
                        } ####end RowCount > 0
                    } #####end Row loop
                } ###### end Default
            } #####end switch
        }  #####end IsAccessible
    }  #####end database loop
} ###end server loop

$bcp = New-Object System.Data.SqlClient.SqlBulkCopy("Data Source=******;Integrated Security=SSPI;Initial Catalog=DBAMonitoring ")
$bcp.DestinationTableName = "dbo.is_sql_tables"
$bcp.WriteToServer($dt);

$Stopwatch.Stop()
$Stopwatch.Elapsed.TotalSeconds
$Stopwatch.Elapsed.TotalMinutes
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...