Get-ADUser 필터 최적화
AD에서 동일한 EmployeeID 값이 2 개 이상의 레코드에 채워지는 사용자 계정을 식별하려고합니다. 아래는 내 코드입니다 (Credit : I 'm using a Show-Progress
function defined here ). Get-ADUser
명령만으로 모든 레코드를 가져 오는 데 2 시간 이상이 걸렸습니다. 다른 단계 (2 ~ 5)는 매우 빠릅니다. 작업을 완료하는 동안 PowerShell을 사용하여이 작업을보다 효율적으로 수행 할 수 있었는지 알고 싶습니다.
Get-ADUser -LDAPFilter "(&(ObjectCategory=Person)(objectclass=user)(employeeid=*))" -Properties $properties -Server $server_AD_GC -ResultPageSize 1000 |
# *ISSUE HERE*
# The Get-ADUser extract process seems to work very slow.
# However, it is important to note that the above command will be retrieving more than 200K records
# NOTE: I've inferred that employeeid is an indexed attribute and is replicated to GlobalCatalogs and hence have used it in the filter
Show-Progress -Activity "(1/5) Getting AD Users ..." |
select $selectPropsList -OutVariable results_UsersBaseSet | Group-Object EmployeeID | Show-Progress -Activity "(2/5) Grouping on EmployeeID ..." | ? { $_.Count -gt 1 } |
Show-Progress -Activity "(3/5) Filtering only dup EmpID records ..." |
select -Exp Group |
Show-Progress -Activity "(4/5) UnGrouping ..." |
Export-Csv "C:\Users\me\op_GetADUser_w_EmpID_Dupes_EntireForest - $([datetime]::Now.ToString("MM-dd-yyyy_hhmmss")).csv" -NoTypeInformation |
Show-Progress -Activity "(5/5) Exporting ..." |
Out-Null
추신 : 또한 먼저 모든 사용자 계정을 csv 파일로 내 보낸 다음 Excel로 사후 처리를 시도했지만 데이터 세트의 크기 때문에 눈살을 찌푸려 야했고 시간과 메모리 문제가 모두 발생했습니다.
어떤 제안이라도 대단히 감사합니다.
답변
$properties
또는에 무엇이 있는지 모르기 때문에 $selectPropsList
귀하의 질문은 실제로 어떤 사용자에게 동일한 EmployeeID가 발급되었는지 확인하는 것뿐입니다.
기본적으로 Get-ADUser는 이미 다음 속성을 반환합니다.
DistinguishedName
, Enabled
, GivenName
, Name
, ObjectClass
, ObjectGUID
, SamAccountName
, SID
, Surname
,UserPrincipalName
따라서 추가로 필요한 것은 EmployeeID뿐입니다. 많은 속성을 수집하려고하면 속도가 느려지므로이를 최소한으로 유지하면 작업 속도를 높이는 데 도움이됩니다.
다음으로 Show-Progress
링크 한 스크립트를 사용하면 스크립트 실행 속도가 상당히 느려집니다. 진행률 표시 줄이 정말로 필요합니까? 단순히 활동 단계가있는 줄을 콘솔에 직접 작성하지 않는 이유는 무엇입니까?
또한 모든 것을 함께 연결하는 것은 속도 부서에서도 도움이되지 않습니다 ..
$server_AD_GC = 'YourServer' $selectPropsList = 'EmployeeID', 'Name', 'SamAccountName', 'Enabled'
$outFile = "C:\Users\me\op_GetADUser_w_EmpID_Dupes_EntireForest - $([datetime]::Now.ToString("MM-dd-yyyy_hhmmss")).csv"
Write-Host "Step (1/4) Getting AD Users ..."
$users = Get-ADUser -Filter "EmployeeID -like '*'" -Properties EmployeeID -Server $server_AD_GC -ResultPageSize 1000
Write-Host "Step (2/4) Grouping on EmployeeID ..."
$dupes = $users | Group-Object -Property EmployeeID | Where-Object { $_.Count -gt 1 } Write-Host "Step (3/4) Collecting duplicates ..." $result = foreach ($group in $dupes) {
$group.Group | Select-Object $selectPropsList
}
Write-Host "Step (4/4) Exporting ..."
$result | Export-Csv -Path $outFile -NoTypeInformation
Write-Host "All done" -ForegroundColor Green
PS는 Get-ADUser
이미 사용자 개체 만 반환하므로 LDAP 필터가 필요하지 않습니다 (ObjectCategory=Person)(objectclass=user)
. 사용하면 -Filter "EmployeeID -like '*'"
아마도 더 빠를 것입니다
이 답변은 보완 테오의 도움이 대답을 하고 에 초점을 맞추고 진행 상황을 보여주는 작업 중 :
연결 Show-Progress기능 이 글을 쓰는 등의 최신입니다 :
파이프 라인 입력을 통과하지 않는다는 점에서 명백한 버그 가 있습니다 (관련 줄이 실수로 주석 처리됨).
process
블록을 사용하지 않는다는 점에서 개념적으로 결함이 있습니다. 즉, 모든 파이프 라인 입력 이 처리되기 전에 먼저 수집 되므로 진행률 표시 줄의 개념이 무효화됩니다.
따라서
Show-Progress
파이프 라인의 이전 명령이 모든 출력을 출력 할 때까지 호출에 진행률이 표시되지 않습니다 . 간단한 대안은 파이프 라인을 별도의 명령으로 나누고 각 명령 전에 단순히 하나의 진행 메시지 를 내보내고 Theo의 답변에 표시된대로 다음 처리 단계 (객체 별 진행이 아님)를 알리는 것입니다.일반적으로 명령 내부 처리 의 진행률을 표시하는 방법은 없으며 명령의 (다중 객체) 출력 의 진행률 만 표시합니다 .
ForEach-Object전화를 통해이 작업을 수행하는 가장 간단한 방법
Write-Progress은 두 가지 문제가 있습니다.쇼를하기 위해 완료율 진행 표시 줄을, 당신은 총있을 것입니다 얼마나 많은 개체를 알 필요가 당신이 결정해야합니다, 미리 때문에, 파이프 라인 이받을 얼마나 많은 개체를 알 수 없다; 유일한 옵션은 먼저 모든 출력 을 수집 한 다음 (또는이를 계산하는 다른 방법을 찾음) 수집 된 출력을 파이프 라인 입력으로 사용하고 전달할 값을 계산하는 기준으로 객체 수를 사용하는 것입니다
Write-Progress -PerCentComplete
.호출
Write-Progress
에 대한 각각의 A의 결과를 수신 할 개체 상당한 침체 전체의 처리; 타협은 이 답변에 표시된 것처럼 모든 N 개체에 대해서만 호출하는 것입니다 . 접근 방식Show-Progress
은 전체 객체 수를 인수로 전달하고 적절한 스트리밍 입력 객체 처리 (process
블록을 통해 ) 를 수행해야하는 적절하게 구현 된 함수로 래핑 될 수 있습니다 . 즉, 입력 개체를 전달하기 위해 PowerShell 코드 를 사용하는 단순한 작업 은 비용이 많이 듭니다.
결론:
완료율 표시에는 두 가지 고유 한 문제가 있습니다 .
처리 할 총 개체 수를 미리 알아야합니다 (파이프 라인은 통과 할 개체 수를 알 수있는 방법이 없음).
다음 중 하나 : 가능한 경우 미리 메모리 에서 처리 할 모든 개체를 수집 합니다 . 그런 다음 컬렉션의 요소 수를 완료율 계산의 기준으로 사용할 수 있습니다. 이것은 매우 큰 입력 세트의 옵션이 아닐 수 있습니다.
또는 : 실제로 검색하지 않고 모든 개체를 계산 하는 추가 처리 단계를 미리 수행 합니다. 이는 추가 처리 시간 측면에서 실용적이지 않을 수 있습니다.
PowerShell 코드 에서 ForEach-Object또는 고급 스크립트 / 함수 를 통한 개체 별 처리 는 본질적으로 느립니다.
- 이 답변에Write-Progress 표시된 것처럼 모든 N 개체 에 대한 호출을 제한하여 다소 완화 할 수 있습니다.
전반적으로 처리 속도와 최종 사용자에게 완료율 진행률 을 표시하는 기능 간의 균형 입니다.