Powershell Merge 2列出了Performance

时间:2017-09-07 08:50:33

标签: performance list powershell join

我在Powershell中有两个包含大量数据的列表:

  • $ Byods包含大约5000个项目的MAC和用户名
  • $ DHCPLeases包含大约3000个项目的MAC和IP

我想创建一个包含Byods列表所在的用户名和IP的新列表,并且从DHCPleases中找到IP,只包含找到匹配的记录(左连接?)

我创建了一个foreach循环,完成了这项工作。但是,它需要花费大量的时间来完成(> 30分钟)。

我相信这可以更快。任何人吗?

$UserByods = @()
foreach ($lease in $DHCPLeases) 
{
    $MAC = [string]$lease.MAC
    $UserByod = @()
    $UserByod = $Byods | where {$_.MAC -eq $MAC}
    if (($UserByod | measure).count -eq 1) {
        $ByodIP = New-Object -TypeName PSObject
        $ByodIP | Add-Member -Name 'User' -MemberType Noteproperty -Value $UserByod.Username
        $ByodIP | Add-Member -Name 'IP' -MemberType Noteproperty -Value $lease.IP
        $UserByods += $ByodIP
    }
}

3 个答案:

答案 0 :(得分:4)

在循环中追加数组很慢。只需在循环中输出自定义对象,并在变量$UserByods中收集循环输出。列表中的线性读取也很慢。更好地从$Byods构建哈希表,以便您可以通过其MAC地址查找设备。

$tbl = @{}
$Byods | ForEach-Object { $tbl[$_.MAC] = $_ }

$UserByods = foreach ($lease in $DHCPLeases) {
    New-Object -TypeName PSObject -Property @{
        'User' = $tbl[$lease.MAC].Username
        'IP'   = $lease.IP
    }
}

答案 1 :(得分:4)

这里可以进行一些改进。首先,不要使用Add-Member来构造对象,它会比预先指定属性慢得多。

您还希望避免在集合上使用加法运算符(+=),因为它会导致调整基础数组的大小,这是一个非常耗费内存的操作。

最后使用散列表进行MAC相关,它比循环遍历所有5000个条目3000次(这是...| Where {...}基本上做的那样)要快得多:

$BYODTable = $Byods |ForEach-Object -Begin { $table = @{} } -Process { $table[$_.MAC] = $_.Username } -End { return $table }

$UserByods = foreach ($lease in $DHCPLeases) 
{
    $MAC = [string]$lease.MAC
    if ($BYODTable.ContainsKey($MAC)) {
        New-Object -TypeName PSObject -Property @{
            User = $BYODTable[$MAC]
            IP   = $lease.IP
        }
    }
}

答案 2 :(得分:0)

我没有您的列表,但我想知道我的Join-Object cmdlet如何执行此操作 命令应该是这样的:

$Byods | LeftJoin $DHCPLeases Mac

我已经在性能方面付出了一些努力,但由于它是一般解决方案,它可能无法与此处给出的具体解决方案竞争......

相关问题