My LDAP/AD DS/AD LDS search is taking pretty long – what can I do?

I’ve had some contact with a few Devs that are trying to build an AD-aware application and was semi-responsible for feeding they questions with great answers. Some of the questions involved simple attribute names or locations where data was stored within the directory, other questions were about performance. Then, just a few minutes ago, I found a question in the Newsgroups that pretty much ended up being an exact copy of the question that I’ve heard a couple of times the last days.

My LDAP search is taking pretty long – why is that? What can I do?

I wont’ go into all the details here but put up a list of questions you may run through and ask yourself and check back that might be a cause of slow/expensive processing of LDAP queries against AD DS/AD LDS.Â

First of all, it’s important to define what “pretty long” means, really. Is it three seconds? Ten seconds? A minute?

HardwareÂ

Make sure hardware is not the cause of the slow responses. Actually, hardware is almost never the cause here but you never know. Check how large your DIT is and how much RAM there is in your DCs. AD tries to fit (most of)the DIT into RAM so it can access it in-memory, saving I/O and valuable time during query processing. Is that machine under constant load? Try to target a different DC/LDS host to gather information from — does that work better?

Attributes searched

Look at the attributes seached. What kind of attributes are part of your filter? Are there attributes that are indexed in AD? (hint: “adfind -sc indexed ldapDisplayName -nodn” for a list of indexed attributes). If there’s no indexed attributes in your query, AD’s going to crawl the whole DIT to search for results (every time!). Help AD be more efficient by either including an indexed attribute in your search filter or indexing an attribute that’s part of your search that currently isn’t indexed. Including an already indexed attribute to your search is probably your best bet here. If you’re searching for users or contacts, try to include that in your search filter ( &(objectClass=user)(objectCategory=person) ). Don’t search for attributes that have little entropy. If 80% of the objects in your directory have a value in attribute x, it’s not worth filtering (x=*). If you’re attribute only has a couple of possible state (preferredHand=left) where only “left” and “right” are possible values, including that attribute to the filter might not shrink the search base noticably.

Try to limit the result base as much as you can by defining the most limiting filter possible.

Question the search base

Where are you searching? Are you using the domain root as a search base when all the results are in an OU somewhere in the tree? Try to be specific from there and how far you want to search. Don’t use “Subtree” searches when you know the search results are direct child objects of a specific OU. If you know where you can expect search results, target the search specifically there. Try to create multiple searches with different search roots — that may be more efficient than searching once and targeting the domain root.

What is actually taking *so* long?

Turn on diagnostics on the server to check whether you’re running inefficient or expensive queries. A good starting point is “Field Engineering” (http://www.frickelsoft.net/blog/?p=243) and Performance Counters.

Un-Complex your search

Try to tearch the search apart. Are you using a lot of NOT (!) operators in your search? You have some wildcard filters (x=*heim) (y=*text*)Â (z=400*)Â in there, too? Try to remove some of the filters one by one and see whether your search performs faster (while keeping an eye on the search results count, of course!)

Compare with other apps

Compare the search with other apps. You have that application in front of you and you know the query it fires to AD? Great, compare the query performance with LDP or ADfind and use their STATS commands/controls to compare the performance. If LDP and ADfind perform well on the same filters, chances are your app just does inefficient things with the search results. Compare the searches right after you rebooted a server with searches after it’s been running for some time. Is there a performance increase? How do ADFind and LDP perform then?

Try to fire up a network trace app (wireshark, network monitor) to see what’s going on on the wire. Is that app targeting a specific LDAP server or is it burning time to find a server using incorrect DNS information? Does it repeat some LDAP queries over and over again? Is the program working correctly i.e. searching the directory by telling it only to return necessary/wanted attributes from the result set or is the whole object torn over the line (I know .NET is a sucker in this!)?

6 Comments so far

  1. Philipp Foeckeler on March 25th, 2010

    Hi Florian, cheers for that article.

    According to attribute-based searches, i have a good speed-up advice for the most often used search filter in AD environments, the one for users: Instead of searching with the usual “(&(objectClass=user)(objectCategory=person))”, just search for “(sAMAccountType=805306368)”. This matches on user accounts also and is far more effective internally.

    Philipp

  2. Patryk Wolski on April 6th, 2010

    One of the important factors of LDAP query is LDAP policy. Ie. messing with page size is something I’ve seen pretty often.

  3. florian on April 6th, 2010

    Thanks Patryk,

    that’s worth another blog posting!

    Cheers,
    Florian

  4. Michael Liben on May 5th, 2010

    I’ve found the most common cause for slow searches is the use of a “not” operator in a search filter clause. The directory must evaluate every object meeting the other criteria in order to determine the object does not contain the attribute (or attribute value).

  5. ewolfman on July 21st, 2011

    Hi Florian,

    Thanks for the info.

    I was wondering whether you can throw some tips at optimizing write performance for AD LDS. We have a dedicated server with 16 CPUs, ~90GB RAM and a 6 disk H700 RAID, for load tests. We noticed a behavior that under stress tests, every several seconds there’s a downfall in write performance of small objects.

    My questions are whether there’s a setting to optimize writes; and whether it’s possible to batch writes (i.e. make ADAM cache writes to maximize performance).

    Thanks.