简体   繁体   English

将 PowerShell 脚本从调用更改为批量复制

[英]Change PowerShell script from Invoke to Bulk Copy

I have used the below code for a little while, mainly as a test to understand it a bit more.我已经使用下面的代码一段时间了,主要是作为一个测试来了解它。 What I would really like to do now is improve it's speed by using bulk copy.我现在真正想做的是通过使用批量复制来提高速度。

The code gets database and table information from a series of instances which are held in a text file on a server, it then adds the collected data via invoke into a table.代码从服务器上的文本文件中保存的一系列实例中获取数据库和表信息,然后通过调用将收集的数据添加到表中。

The issue is it sends the data for every database, and every table one at a time, if at all possible.问题在于,如果可能的话,它会一次发送每个数据库和每个表的数据。

I have looked at a number of sites/blogs that give information on this, but they all seem to be not quite what I need.我查看了许多提供这方面信息的网站/博客,但它们似乎都不是我所需要的。

$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

One way is to load the rows into a DataTable and use .NET SqlBulkCopy directly in the script to bulk insert.一种方法是将行加载到 DataTable 中,并在脚本中直接使用 .NET SqlBulkCopy 进行批量插入。 Just change the DataTable column names and data types in the below example to match those of your actual table.只需更改以下示例中的 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM