【问题标题】:Powershell SqlCommand and StreamWriter slow writePowershell SqlCommand 和 StreamWriter 慢写
【发布时间】:2023-04-05 09:06:01
【问题描述】:

我正在编写一个从数据库中提取任意 SQL 查询的 PowerShell 脚本。这些查询可能会变得非常大,在尝试 sqlcmd 之后,我最终得到了 StreamWriter / SqlCommand 组合。我遇到的问题是执行有点慢。就像 10 倍一样慢。我被告知它应该更快,因此问题。 编码!

                $conn.ChangeDatabase("MyDB")
                $mycmd = new-object System.Data.SqlClient.SqlCommand($Myquery, $conn) 
                $mycmd.CommandType = [System.Data.CommandType]::Text
                $mycmd.CommandTimeout = 300
                echo "Executing Reader."        
                $Results = $mycmd.ExecuteReader()


                echo "Opening file for writing."                    
                $sw2 = new-object system.IO.StreamWriter($sqlOutput, 1)
                echo "File Opened for Writing."     
                $delimiter = ","
                echo "Starting Row Reading"
                $Counter = $Results.FieldCount
                echo $Counter
                # Put in header row on first execution.
                $currtext = ""
                if ($Counter -gt 0)
                {
                    echo "Writing Header Row as:"
                    for ($i = 0; $i -lt $Counter; $i++)
                    {
                        $currtext = $currtext + $Results.GetName($i)
                        if ($i -lt $Counter - 1)
                        {$currtext = $currtext + $delimiter}
                    }

                    echo $currtext
                    $sw2.writeline($currtext)
                    $firstexecution = 0
                }
                else
                {
                    $sw2.writeline("No Data Found")
                }

                $rowcount = 0
                while ($Results.Read())
                {
                    $rowcount = $rowcount + 1
                    #echo "Reading Row"
                    $i = 0
                    $currtext = ""
                    for ($i = 0; $i -lt $Counter; $i++)
                    {
                        #echo "Processing Row"
                        $currtext = $currtext + """" + [string]$Results[$i] + """" 
                        if ($i -lt $Counter - 1)
                            { $currtext = $currtext + $delimiter }
                    }
                    #echo "Writing Line."
                    #echo $currtext
                    $sw2.writeline($currtext)
                }
                echo "Total Rowcount:" + $rowcount
                $sw2.flush()
                $sw2.close()
                $sw2.dispose()
                $Results.close()

有人知道我做错了什么/如何解决吗?

【问题讨论】:

  • 如果你真的说当它变慢时会有很大帮助。您在脚本中收到了很多回声,那么在它变得非常慢之前的最后一条消息是什么?此外,sqlcmd 可能会更快(我还没有测试过),因为使用 powershell 您需要生成对象等,而 sqlcmd 可以只写下未解析的行。
  • 从性能的角度来看,重要的块是逐行读取的部分,即 while 循环。 while 循环目前可以每分钟读取/写入大约 5 兆的数据,这似乎很慢。

标签: performance powershell file-io streamwriter sqlcommand


【解决方案1】:

添加管理单元:

Add-PSSnapin SqlServerCmdletSnapin100
Add-PSSnapin SqlServerProviderSnapin100

调用你的变量:

$SQLUsername        = "user"
$SQLPassword        = "password"
$SQLDatabase        = "database"
$SQLServer          = "localhost"

获取您的数据:

$DBComputers = Invoke-Sqlcmd -ServerInstance $SQLServer -Username $SQLUsername -Password $SQLPassword `
 -Database $SQLDatabase -Query "SELECT * FROM Physical WHERE Retired=0 AND OS LIKE '%Windows%' ORDER BY Name"

遍历行:

foreach ( $DBComputer in $DBComputers ) {

    Write-Host $DBComputer.Name    ##$DBComputer.COLUMNNAME

}

通过使用上面的以下示例,我已经使用 PowerShell 完成了很多 SQL。上面的示例以非常快的速度查询戴尔 R720 服务器上的 SQL 标准实例上的数据。这是 Microsoft Access 数据库还是真正的 SQL 实例?访问引擎并不理想,而且根据您的磁盘类型会很重要。

您提到了一个大型数据集,我认为最重要的是确保数据库被索引并运行真正的 SQL 引擎,而无需从非代码角度了解更多关于数据库的信息。

【讨论】:

  • 这是一个真正的 SQL 实例,由于查询是任意的,因此结构并不重要。问题在于数据吞吐量。而且问题相当大;在我最近遇到的实例中,数据约为 100MB。我以前使用 SQLCMD,但误诊为内存/大小问题(我用于写入 ZIP 文件的缓冲区在 100MB 处内存不足)并将其重写为使用 StreamWriter。我很好奇为什么我的性能差异如此之大。
  • 你可能在做不必要的循环?不完全确定,但是如果您可以简单地执行以下操作以将其全部转换为 CSV 格式,那么您可以在此示例中进行操作,因为这几乎是您正在做的事情,只需手动操作即可。 Invoke-Sqlcmd -Query "SELECT * FROM Physical" | Export-Csv -Path C:\Export.csv -NoTypeInformation
  • Export-Csv 能否很好地管理字段引用? Invoke-Sqlcmd 具有选择分隔和导出的选项,但输出并没有像它需要的那样干净。作为旁注,我之前的实现是: sqlcmd -Q $Myquery -d $CurrentDB -S $CurrentServer -o $sqlOutput -E -k -W -s " " -t 500
  • Export-Csv 具有使用-Delimiter "," Export-CSV Link 定义分隔符的参数。这当然是实验,但我不明白为什么如果需要它不会保留报价。有引用-I enable Quoted Identifiers的参数见MSDN Link
  • 引用标识符并不一定意味着数据将被引用。我尝试用 -s """,""" 替换 -s " (tab char here) " ,它给了我想要的输出。
猜你喜欢
  • 2016-08-11
  • 2021-07-10
  • 2015-04-28
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
  • 2015-09-17
  • 2013-01-13
相关资源
最近更新 更多