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

时间:2018-04-10 16:25:05

标签: c# ldap directoryservices directorysearcher

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

这个问题与this非常相似,基本上我是通过以下代码从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;

以上返回SearchResultCollection即时(约4毫秒),无论结果量多少(服务器是具有大量资源的2012-R2 VM)或返回的属性,当任何尝试访问时都会出现问题SearchResultCollection,包括SearchResultCollection.Count

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

这通常会非常好,但在较慢的PC上,即使50个结果也需要30秒以上。

速度受SearchResultCollection中的速度影响,例如,如果我添加searchdirectory.PropertiesToLoad.Add("cn"),则需要花费一小部分时间(1/10或更低)。所以我假设问题源于SearchResultCollection内的数据量和缓存/移动到内存或类似的时间(编程时仍然有点新)。 如果我更改正在搜索的字段,它也会产生很大的不同,但这不会产生影响,因为时间问题是访问SearchResultCollection而不是调用FindAll()时。

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

如果有人能够以任何方式(通过示例或指向学习资源)提供帮助,使这些代码更有效地运行而不会严重影响返回的属性或搜索参数,那么这也将是一件好事。

我知道Powershell可以立即检索到这些类型的细节,所以我认为必须有一个更好的方法解决这个问题。

1 个答案:

答案 0 :(得分:0)

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

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

是的,查询会影响性能。这取决于您正在搜索的属性。在这种情况下,telephoneNumber未编入索引。这意味着它必须查看每个帐户来查看电话号码。我怀疑如果你只是删除那个条件,那么你的查询会更快。

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

正如EricLavault所说,你应该处理结果。来自the documentation for FindAll()

  

由于实施限制,SearchResultCollection类   当它是垃圾时,无法释放所有非托管资源   集。要防止内存泄漏,必须调用Dispose方法   当不再需要SearchResultCollection对象时。