【问题标题】:Powershell progress bar for invoke-sqlcmdinvoke-sqlcmd 的 Powershell 进度条
【发布时间】:2018-07-27 07:27:39
【问题描述】:

所以我尝试制作一个备份脚本,该脚本将从我的 mssql 下载 csv,然后压缩文件,然后将备份上传到亚马逊 S3。

我遇到的问题是,当我每天运行脚本时,表格平均有 2000 万行。看起来它只是永​​远滞后,直到它在 20 分钟后完成。我想知道是否有办法专门为 invoke-sqlcmd 显示进度条。我做了一些研究,我能找到的所有示例都是仅在 for 循环上制作进度条,而不是单个命令进度。

这是我的代码:

ECHO "Starting Download"
    Import-Module sqlps
    #$SQLquery="SELECT * FROM dbo.$PREFIX$i"
    $SQLquery="SELECT * FROM dbo.events"
    ECHO "Executing query = $SQLquery"

    $hostname = "."
    $pass = "test"
    $usern = "test"
    $database = "theDB"

    $result=invoke-sqlcmd -ServerInstance $hostname  -query $SQLquery -HostName $hostname -Password $pass -Username $usern -Database $database -verbose


    #echo $result
    pause
    $result |export-csv -path $CSVPATH -notypeinformation
    pause
    ECHO "Starting Zip:"
    Compress-Archive -LiteralPath $CSVPATH -CompressionLevel Optimal -DestinationPath $ZIPPATH

    ECHO "Starting Delete: $CSVPATH "
    del "$CSVPATH" 
    echo "Removed $CSVNAME" 

    aws s3 cp $ZIPPATH s3://test_$ZIPNAME

    pause

这个脚本可以工作,但正如我所说,我想在 invoke-sqlcmd 中添加一个进度条,这样它在下载大文件时就不会被冻结。

这是我目前能找到的,但这仅适用于循环进程

$VerbosePreference = "Continue"
Write-Verbose "Test Message"

for ($a=1; $a -lt 100; $a++) {
  Write-Progress -Activity "Working..." -PercentComplete $a -CurrentOperation "$a% complete" -Status "Please wait."
  Start-Sleep -Milliseconds 100
}

【问题讨论】:

  • bcp 怎么样?它会在提取数据的同时打印进度。
  • 或者你可以分批下载这个——比如:检查大小,分成 10 个部分并在 10 次迭代中下载?然后您可以根据迭代次数下降来编写进度,并且 - 如果任何较小的批次由于任何原因而失败,则可以恢复下载:)。

标签: powershell progress-bar


【解决方案1】:

考虑到您庞大的约 2000 万条记录数据集,使用 System.Data.Common namespace 中的一些 .NET 类可能是个好主意。而且我不确定Export-Csv是如何实现的,但是System.IO.StreamWriter对于写大文件非常有效。

带有内联 cmets 的简单测试/工作示例:

# replace $tableName with yours
$sqlCount = "SELECT COUNT(*) FROM dbo.$($tableName)";
$sqlSelect = "SELECT * FROM dbo.$($tableName)";
$provider = [System.Data.Common.DbProviderFactories]::GetFactory('System.Data.SqlClient');
$connection = $provider.CreateConnection();
# replace $connectionString with yours, e.g.:
# "Data Source=$($INSTANCE-NAME);Initial Catalog=$($DATABASE-NAME);Integrated Security=True;"; 
$connection.ConnectionString = $connectionString;
$command = $connection.CreateCommand();

# get total record count for Write-Progress
$command.CommandText = $sqlCount;
$connection.Open();
$reader = $command.ExecuteReader();
$totalRecords = 0;
while ($reader.Read()) {
    $totalRecords = $reader[0];
}
$reader.Dispose();

# select CSV data
$command.CommandText = $sqlSelect;
$reader = $command.ExecuteReader();

# get CSV field names
$columnNames = @();
for ($i = 0; $i -lt $reader.FieldCount; $i++) {
    $columnNames += $reader.GetName($i);
}

# read and populate data one row at a time
$values = New-Object object[] $columnNames.Length;
$currentCount = 0;
# replace $CSVPATH with yours
$writer = New-Object System.IO.StreamWriter($CSVPATH);
$writer.WriteLine(($columnNames -join ','));
while ($reader.Read()) {
    $null = $reader.GetValues($values);
    $writer.WriteLine(($values -join ','));
    if (++$currentCount % 1000 -eq 0) {
        Write-Progress -Activity 'Reading data' `
            -Status "Finished reading $currentCount out of $totalRecords records." `
            -PercentComplete ($currentCount / $totalRecords * 100);
    }
}
$command.Dispose();
$reader.Dispose();
$connection.Dispose();
$writer.Dispose();

【讨论】:

  • 非常感谢会使用它:)
猜你喜欢
  • 2016-01-15
  • 1970-01-01
  • 2012-09-13
  • 2014-04-15
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-07
相关资源
最近更新 更多