Более быстрая итерация - PullRequest
       20

Более быстрая итерация

0 голосов
/ 08 октября 2018

У меня есть этот код, который является частью функции, которая возвращает список строк SQL на основе временного диапазона.

Сам запрос (1-я строка кода) довольно быстрый.Но цикл foreach, который извлекает релевантные данные, требует времени для завершения.

У меня есть около 350 000 строк для повторения, и, несмотря на то, что это займет некоторое время, мне было интересно, есть ли какие-нибудь изменения, которые я мог бы сделатьсделать для того, чтобы сделать это быстрее.

$SqlDocmasterTableResuls = $this.SqlConnection.GetSqlData("SELECT DOCNUM, DOCLOC FROM MHGROUP.DOCMASTER WHERE ENTRYWHEN between '" + $this.FromDate + "' and '" + $this.ToDate + "'")

[System.Collections.ArrayList]$ListOfDocuments = [System.Collections.ArrayList]::New()

if ($SqlDocmasterTableResuls.Rows.Count)
{
    foreach ($Row in $SqlDocmasterTableResuls.Rows)
    {
        $DocProperties = @{
            "DOCNUM"      = $Row.DOCNUM
            "SOURCE"      = $Row.DOCLOC
            "DESTINATION" = $Row.DOCLOC -replace ([regex]::Escape($this.iManSourceFileServerName + ":" + $this.iManSourceFileServerPath.ROOTPATH)),
                            ([regex]::Escape($this.iManDestinationFileServerName + ":" + $this.iManDestinationFileServerPath.ROOTPATH))
        }

        $DocObj = New-Object -TypeName PSObject -Property $DocProperties
        $ListOfDocuments.Add($DocObj)
    }

    return $ListOfDocuments

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

[edit - согласно Ansgar Wiechers, ускоритель PSCO доступен только с ps3 +.]

еще одна вещь, которая может помочь, это заменить New-Object на [PSCustomObject].это обычно несколько быстрее в использовании.что-то вроде этого ...

$DocObj = [PSCustomObject]$DocProperties

Другой способ использовать этот ускоритель типов - сделать то, что сделал Ансгар Вичерс в своем примере кода, но использовать вместо командлета ускоритель.вот так ...

[PSCustomObject]@{
    'DOCNUM'      = $Row.DOCNUM
    'SOURCE'      = $Row.DOCLOC
    'DESTINATION' = $Row.DOCLOC -replace $srcPath, $dstPath
    }

надеюсь, это поможет,
ли

0 голосов
/ 08 октября 2018

Избегайте добавления в массив в цикле.Лучший способ получить данные цикла в переменной - просто собрать выходные данные цикла в переменной:

$ListOfDocuments = foreach ($Row in $SqlDocmasterTableResuls.Rows) {
    New-Object -Type PSObject -Property @{
        "DOCNUM"      = $Row.DOCNUM
        "SOURCE"      = $Row.DOCLOC
        "DESTINATION" = $Row.DOCLOC -replace ...
    }
}

Вам не нужно окружающее условие if, потому что если в таблице нетЛюбые строки, которые цикл должен пропустить, оставляя вас с пустым результатом.

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

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

$srcPath = [regex]::Escape($this.iManSourceFileServerName + ':' + $this.iManSourceFileServerPath.ROOTPATH)
$dstPath = [regex]::Escape($this.iManDestinationFileServerName + ':' + $this.iManDestinationFileServerPath.ROOTPATH)

и используйте переменные $srcPath и $dstPath внутри цикла.

Что-то подобное должно сделать:

$SqlDocmasterTableResuls = $this.SqlConnection.GetSqlData("SELECT ...")

$srcPath = [regex]::Escape($this.iManSourceFileServerName + ':' + $this.iManSourceFileServerPath.ROOTPATH)
$dstPath = [regex]::Escape($this.iManDestinationFileServerName + ':' + $this.iManDestinationFileServerPath.ROOTPATH)
foreach ($Row in $SqlDocmasterTableResuls.Rows) {
    New-Object -Type PSObject -Property @{
        'DOCNUM'      = $Row.DOCNUM
        'SOURCE'      = $Row.DOCLOC
        'DESTINATION' = $Row.DOCLOC -replace $srcPath, $dstPath
    }
}

return
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...