来自 LDAP 请求的 SearchResultCollection 的性能问题

Performance issue with a SearchResultCollection from an LDAP request

我在自己创建的 Active Directory 搜索工具中遇到了一些性能问题。

这个问题与 一个非常相似,本质上我是通过以下代码从 AD 中检索用户列表:

DirectoryEntry dEntry = new DirectoryEntry("LDAP://ldappath");
DirectorySearcher searchdirectory = new DirectorySearcher(directory);

searchdirectory.Filter = "(&(objectClass=user)(objectcategory=person)(|(name=" + searchString + "*)(givenname=" + searchString + "*)(sn=" + searchString + "*)(mail=" + searchString + "*)(telephonenumber=" + searchString + "*)(samaccountname=" + searchString + "*)))";
searchdirectory.Sort.PropertyName = "name"; // Optional sorting by attribute
searchdirectory.SizeLimit = 100; // Sets the search limit
searchdirectory.PageSize = 1000; // Sets the results per returned page

SearchResultCollection collectionResults = searchdirectory.FindAll();

directory.Dispose();
searchdirectory.Dispose();

List<SearchResult> results = new List<SearchResult>();

for (int i = 0; collectionResults.Count > i; i++)
{
    results.Add(collectionResults[i]);
}

return results;

以上returns SearchResultCollection 无论结果量(服务器是2012-R2 VM,具有大量资源)或返回的属性如何,都会立即(~4ms),问题当任何尝试访问 SearchResultCollection 时发生,包括 SearchResultCollection.Count.

所有属性的10个结果和searchString为空,大约需要65ms,100个结果需要240ms,1000个需要1950ms。搜索实际字符串似乎会向任意数量的结果添加 ~350 毫秒,无论结果数或搜索字符串如何。与“*a”相比,搜索 "a" 似乎也更慢。

这通常很好,但在速度较慢的 PC 上,即使是 50 个结果也可能需要 30 多秒。

速度受 SearchResultCollection 中内容的影响,例如,如果我添加 searchdirectory.PropertiesToLoad.Add("cn"),则只需要一小部分时间(1/10 或更少)。因此,我假设问题源于 SearchResultCollection 中的数据量以及 cache/move 将其存储到内存或类似设备所需的时间(对于编程来说仍然有点新)。 如果我更改它搜索的字段也会有很大的不同,但这应该不会有什么不同,因为时间问题是在访问 SearchResultCollection 时而不是在调用 FindAll().[=24 时=]

我想知道并澄清的是,为什么在访问 SearchResultCollection 而不是在实际执行搜索时需要时间,据我所知,当我调用时它应该从 LDAP 检索所有结果FindAll().

如果有人可以以任何方式(通过示例或指向学习资源)帮助使此代码 运行 更有效,而不会严重影响返回的属性或搜索参数,那就太好了.

我知道 Powershell 可以立即检索这些类型的详细信息,所以我认为一定有更好的方法来解决这个问题。

在您实际访问列表之前,各种类型的列表不完全可用在 .NET 中是很常见的。所以这部分并不奇怪。

此外,如果您未设置 PropertiesToLoad,则结果中的每个帐户都会返回 所有 具有值的属性。因此,最好只将 PropertiesToLoad 设置为您需要的属性。

是的,查询会影响性能。这取决于您要搜索的属性。在这种情况下,telephoneNumber 没有被索引。这意味着它必须查看 每个帐户 以检查 phone 号码。我怀疑如果你只是删除那个条件,那么你的查询会快得多。

这可能对你有帮助,也可能没有帮助,但你可以看看 Ambiguous Name Resolution。您在 LDAP 查询中使用它 (anr=" + searchString + ")",AD 将搜索各种属性(在文档中列出)。

正如 EricLavault 提到的,您应该处理结果。来自 the documentation for FindAll():

Due to implementation restrictions, the SearchResultCollection class cannot release all of its unmanaged resources when it is garbage collected. To prevent a memory leak, you must call the Dispose method when the SearchResultCollection object is no longer needed.