简体   繁体   English

慢 Get-ADUser 查询

[英]Slow Get-ADUser query

Something I do not unterstand.我不理解的东西。 See the following two code examples.请参阅以下两个代码示例。

  $LDAPResult1 = Get-ADUser -LDAPFilter "(&(objectCategory=user)(sAMAccountName=*))" -Properties @("distinguishedName","sAMAccountName","extensionAttribute13") -SearchBase "ou=test,dc=test,dc=ch"
  $LDAPElements1=@{}
  $LDAPResult1 |% {$LDAPElements1.Add($_.SAMAccountName, $_.extensionattribute13)}

compared with (adding a specific server to ask "-Server 'dc.test.test.ch'"):与(添加特定服务器以询问“-Server 'dc.test.test.ch'”):

  $LDAPResult1 = Get-ADUser -LDAPFilter "(&(objectCategory=user)(sAMAccountName=*))" -Properties @("distinguishedName","sAMAccountName","extensionAttribute13") -SearchBase "ou=test,dc=test,dc=ch" -Server 'dc.test.test.ch'
  $LDAPElements1=@{}
  $LDAPResult1 |% {$LDAPElements1.Add($_.SAMAccountName, $_.extensionattribute13)}

The first code takes 30 seconds, the second about 5 minutes.第一个代码需要 30 秒,第二个大约需要 5 分钟。 The problem ist not the AD query.问题不在于 AD 查询。 This takes around 30 seconds in both cases.在这两种情况下,这大约需要 30 秒。 But filling the result into the hash table is what is differnet.但是将结果填充到哈希表中是不同的。 It seems as if in the second case while filling the hash sill some data is requested from the DC.似乎在第二种情况下,在填充哈希基台时,需要从 DC 请求一些数据。

What is also interesting.还有什么有趣的。 When I wait for five minutes after doing the AD query in case two and then execute the filling into the hash table, then the command takes a second.当我在做 AD 查询后等待五分钟,然后执行填充到哈希表中时,该命令需要一秒钟。

I rather would likt to define to what server the command connects in order to execute the folloing commands on the same DC, but this does not make sense if it takes that long.我宁愿定义命令连接到哪个服务器以便在同一个 DC 上执行以下命令,但是如果需要那么长时间,这没有意义。

Can anyone enlighten me …谁能给我解惑...

Addition: We are Talking about 26'000 accounts.补充:我们谈论的是 26'000 个帐户。

I was able to replicate this.我能够复制这一点。 The behaviour does change when you specify the -Server parameter vs. when you don't.当您指定-Server参数与不指定时,行为确实会发生变化。

I usedProcess Monitor to watch network activity and it definitely is talking to the DC when looping through the results returned from using the -Server parameter.我使用Process Monitor来观察网络活动,当循环使用-Server参数返回的结果时,它肯定是在与 DC 对话。

I can't explain why, but it seems like the ADUser objects returned are not populated with the properties from the search.我无法解释原因,但返回的ADUser对象似乎没有使用搜索中的属性填充。 So when they are accessed, it loads the properties from the DC.因此,当它们被访问时,它会从 DC 加载属性。 I could see this when accessing one particular element in the array:在访问数组中的一个特定元素时,我可以看到这一点:

$LDAPResults1[1000]

It displayed the properties, but I also saw network activity in Process Monitor.它显示了属性,但我也在 Process Monitor 中看到了网络活动。 Whereas I do not see network activity when accessing one element from the results returned when not using the -Server parameter.而从不使用-Server参数时返回的结果中访问一个元素时,我没有看到网络活动。

So that kind of explains what is happening, but not why .所以,那种解释发生了什么,而不是原因 And I really don't know why.我真的不知道为什么。

However, I have learned that if you want performance when talking to AD, you have to scrap all the "easy" ways and do things yourself.但是,我了解到,如果您在与 AD 交谈时想要性能,则必须放弃所有“简单”的方法并自己做事。 For example, use the .NET DirectoryEntry and DirectorySearcher classes directly, which can be done in PowerShell using the "type accelerators" [adsi] and [adsisearcher] .例如,直接使用 .NET DirectoryEntryDirectorySearcher类,这可以在 PowerShell 中使用“类型加速器” [adsi][adsisearcher] For example, this will do the same and will perform consistently:例如,这将执行相同的操作并始终如一地执行:

$dc = "dc.test.test.ch"
$searchBase = "ou=test,dc=test,dc=ch"
$searcher = [adsisearcher]::new([adsi]"LDAP://$dc/$searchBase", "(objectCategory=user)")

$searcher.PropertiesToLoad.Add("sAMAccountName") > $null
$searcher.PropertiesToLoad.Add("extensionAttribute13") > $null

$searcher.PageSize = 1000

$LDAPElements1=@{}
foreach ($result in $searcher.FindAll()) {
    $LDAPElements1.Add($result.Properties["sAMAccountName"][0], $result.Properties["extensionAttribute13"][0])
}

Export Get-ADUser results into a temporary CSV file and import it back to some objects.将 Get-ADUser 结果导出到临时 CSV 文件中,然后将其导入回某些对象。

Get-ADUser -LDAPFilter (....) | Export-Csv -Path "TempCSV.csv" -Encoding UTF8 -Delimiter ","
$ADUsers = Import-Csv -Path "TempCSV.csv" -Encoding UTF8 -Delimiter ","

Now you can loop the users object.现在您可以循环用户对象。

foreach ($ADUser in $ADUsers) { (....) }

I found the following code to be extremely slow.我发现以下代码非常慢。

$user = Get-ADUser -LDAPFilter $filter  -Server "xyc" -Properties "sAMAccountName"

I was able to rewrite it as:我能够将其重写为:

$directorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$directorySearcher.SearchRoot = [ADSI]'LDAP://xyz'
[void]$directorySearcher.PropertiesToLoad.Add('cn')
[void]$directorySearcher.PropertiesToLoad.Add('sAMAccountName')
$directorySearcher.Filter = "(cn=abcd efg)"
$results = $directorySearcher.FindOne()
Write-Host $results.Properties["samaccountname"] -as [String]

and it was a lot faster (by an order of magnitude) than using GetAd-User (but still slow).它比使用 GetAd-User 快很多(一个数量级)(但仍然很慢)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM