我在我创建的一个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可以立即检索到这些类型的细节,所以我认为必须有一个更好的方法解决这个问题。
答案 0 :(得分:0)
在.NET中,各种类型的列表在您实际访问列表之前不能完全可用,这很常见。所以这部分并不令人惊讶。
此外,如果您未设置PropertiesToLoad
,则会为结果中的每个帐户返回所有带有值的属性。因此,最好将PropertiesToLoad
设置为仅需要的属性。
是的,查询会影响性能。这取决于您正在搜索的属性。在这种情况下,telephoneNumber
未编入索引。这意味着它必须查看每个帐户来查看电话号码。我怀疑如果你只是删除那个条件,那么你的查询会更快。
这可能会对您有所帮助,但您可以查看Ambiguous Name Resolution。您可以在LDAP查询(anr=" + searchString + ")"
中使用它,AD将搜索各种属性(在文档中列出)。
正如EricLavault所说,你应该处理结果。来自the documentation for FindAll()
:
由于实施限制,SearchResultCollection类 当它是垃圾时,无法释放所有非托管资源 集。要防止内存泄漏,必须调用Dispose方法 当不再需要SearchResultCollection对象时。