0

我有一个小过程来摄取 .xel 文件,使用 dba-tools 模块将其转换为自定义对象,然后将它们转换为单行 JSON 并将它们导出到一个文件,该文件可以发送到任何地方。这里:

    $path = 'C:\temp\big_xe_file.xel'

    #Read in file
    $xes = Read-DbaXEFile -Path $path

    #Output Variable
    $file = ""
    foreach ($xe in $xes) {

        #format date column
        $xe.timestamp = ($xe.timestamp.DateTime).ToString("yyyy-MM-ddThh:mm:ss.ffff")

        # convert to JSON and change escaped unicode characters back
        $xe = (($xe | ConvertTo-Json -compress)) | % {                                                                                           #| % { [System.Text.RegularExpressions.Regex]::Unescape($_) }
                                          [Regex]::Replace($_, 
                                             "\\u(?<Value>[a-zA-Z0-9]{4})", {
                                                 param($m) ([char]([int]::Parse($m.Groups['Value'].Value,
                                                     [System.Globalization.NumberStyles]::HexNumber))).ToString() } )}

        #Write line to file
        Add-Content -Value "$($xe)`n" -Path 'C:\temp\myevents.json' -Encoding utf8 -NoNewline

    }

这符合要求,并且完全符合我的需要。中间那个讨厌的正则表达式是因为当你转换为 json 时,它会轻松地转义所有 unicode 字符,而正则表达式会神奇地将它们全部变回我们熟悉和喜爱的字符。

但是,这一切都太慢了。我们大量生成 .xel 文件,通常大小为 500mb,我们希望在写入和摄取跟踪之间有更短的延迟。就目前而言,以这种方式串行处理文件大约需要 35 分钟。如果我们落后,延迟可能会增加,这似乎很可能以那个速度。

我已经加快了速度。我尝试使用 [System.Text.RegularExpressions.Regex]::Unescape 代替我拥有的正则表达式代码,但它只是稍微快一点,并且无论如何都不能提供我们需要的正确格式。我的下一步是将文件拆分为更小的部分并并行处理它们,但这将显着增加 CPU 密集度,如果可能的话,我想避免这种情况。

任何帮助优化这个非常感谢!

4

1 回答 1

0

事实证明存在配置问题,我们能够抛弃正则表达式的废话并将转义字符留在 JSON 中。但是,我也确实找到了加快速度的解决方案,以防万一有人看到这一点。解决方案是将编写器更改为使用 .NET 类而不是 powershell 方法

$stream = [System.IO.StreamWriter] $outfile

foreach ($xe in $xes) {

    #format date column
    $xe.timestamp = ($xe.timestamp.DateTime).ToString("yyyy-MM-ddThh:mm:ss.ffff")

    $xe | Add-Member -MemberType NoteProperty -Name 'source_host_name' -Value $server_name

    # convert to JSON and change escaped unicode characters back
    $xe = (($xe | ConvertTo-Json -compress)) #| % {                                                                                           #| % { [System.Text.RegularExpressions.Regex]::Unescape($_) }
                                             # [Regex]::Replace($_, 
                                             #    "\\u(?<Value>[a-zA-Z0-9]{4})", {
                                             #        param($m) ([char]([int]::Parse($m.Groups['Value'].Value,
                                             #            [System.Globalization.NumberStyles]::HexNumber))).ToString() } )}

    #Add-Content -Value "$($xe)`n" -Path 'C:\DBA Notes\Traces\Xel.json' -Encoding utf8 -NoNewline



    $stream.WriteLine($xe)



}

$stream.close()

它需要 1/10 的时间。干杯

于 2019-09-24T20:00:19.420 回答