LDAP query performance

The other day I was having a discussion with a co-worker about Active Directory performance related to standard LDAP queries. The complaint (and basis for my involvement in the discussion) was based around poor LDAP performance, which was assumed to be attributed to LDAP queries hitting domain controllers contained within virtual machines. This assumption was based on the fact that some queries completed quickly while similar queries were much slower. After some discussion, and viewing the queries, I believed the problem to be more likely attributed to poorly designed queries, so I set off to prove this with actual data.

The queries included as part of this discussion were searching an attribute that was indexed and part of the partialAttributeSet (replicated to Global Catalogs). The queries that completed faster contained a specific value to search while the slow queries had multiple wildcards included in their value. To prove my hypothesis, I created a simple script to perform the same LDAP searches several times, some with specific values, some with a single wildcard and others with multiple wildcards:

[cc lang=”powershell”]
$report = @()
for($i=1; $i -le 5; $i++) {
$item = “” | select Count, SpecificValue, SingleWildcard, TwoWildcards
$item.count = $i
$item.SpecificValue = (Measure-Command { get-dn user mail “testuser@test.domain” }).TotalMilliseconds
$item.SingleWildcard = (Measure-Command { get-dn user mail “testuser*” }).TotalMilliseconds
$item.TwoWildcards = (Measure-Command { get-dn user mail “*tuser*” }).TotalMilliseconds
$report += $item

*Note: Get-DN is a custom function created by a co-worker. It is a PowerShell function I have loaded in my profile that performs a global catalog search. It builds the LDAP filter using three arguments: 1.) the objectCategory to search 2.) the attribute to search 3.) the value to search for in attribute.

The results of the searchs can be seen below:

Count SpecificValue SingleWildcard TwoWildcards
----- ------------- -------------- ------------
    1        9.5489         9.3398   11066.8601
    2        7.7018          7.335   11102.0755
    3        7.8635         8.3801   11067.5442
    4        8.0664         7.6145   11137.9768
    5       10.2233         8.9622   11132.9646

The averages speak volumes about this test:

Property : SpecificValue
Average  : 8.68078

Property : SingleWildcard
Average  : 8.32632

Property : TwoWildcards
Average  : 11101.48424

As I expected, placing multiple wildcards in an LDAP search greatly impacts search performance — even if the attribute being searched is indexed. What I found somewhat surprising is that a single wildcard has nearly no impact on performance — actually in the test a single wildcard slightly outperformed the search of a specific value (but only by a fraction of a millisecond).

I performed these same queries several times and hard-coded the server names to search to include 1.) physical GC only 2.) virtual GC only 3.) allow DNS to resolve domain name to obtain GC name. Each result set was very similar (within fractions of milliseconds) so I included the default result set where DNS resolves the domain name to obtain a GC.

This article is filed under scripting (and not virtualization) because the results prove that using inefficient queries creates more impact on LDAP directory performance than whether you have physical or virtual domain controllers.

Export, Compare, and Synchronize Active Directory Schemas

I’ve had this link in my notes for a long time. I’ve only used it twice, but thought it was worth sharing. If you ever need to make a test Active Directory for some really crazy testing, and you’ve ever extended the schema, you may want those extended attributes. There is a really good article over at Microsoft Technet that walks through this process: http://technet.microsoft.com/en-us/magazine/2009.04.schema.aspx?pr=blog

I’ll generalize the steps…but this is basically what is going on:

  • Exporting the existing schema using LDIFDE
  • Comparision to another schema using AD DS/LDS Schema Analyzer
  • Exporting the schema differences (using AD DS/LDS Analyzer)
  • Importing the schema differences into the target forest

The instructions are pretty straight forward, so just take a look here if you are interested: http://technet.microsoft.com/en-us/magazine/2009.04.schema.aspx?pr=blog

Get ActiveSync Users

When you have almost 30,000 mailboxes, managing ActiveSync can become a nightmare.  The nice thing about ActiveSync is that is just works.  There is not too much configuration to get it setup, but if you do not plan ahead, you can find yourself in the same predicament as us and have 1500 people connecting through some sort of mobile device without any sort of security policy.  This is a huge security risk, and to combat it we are slowy implementing security policies by agency. So the first step in my process was to get a list of all users that have connected in the last 30 days.

So this way takes a long time if you have lots of mailboxes. For example, this takes over 55 minutes to complete in our environment. But if you do not have a lot of mailboxes, then this method should work fine for you. This report will create a CSV, and list the users name, and type of device.

Get-Mailbox -ResultSize:Unlimited | ForEach {Get-ActiveSyncDeviceStatistics -Mailbox:$_.Identity -ErrorAction SilentlyContinue}| Where{$_.LastSuccessSync -gt '01/01/11'} | Sort-Object -Property DeviceType,Identity | Select-Object @{name="EmailAddress";expression={$_.Identity.ToString().Split("\")[0]}},DeviceType | Export-Csv -Path:"c:\MobileDevices.csv"

One of the bad things about the above script is it will more than likely return some dupilcates. So to combat that, I added a where statement just so I can get the devices that have synced in the last 30 days.

get-mailbox -ResultSize unlimited -Filter {EmailAddresses -like "*@email.com" } | ForEach {Get-ActiveSyncDeviceStatistics -Mailbox:$_.Identity  -ErrorAction SilentlyContinue}| where {$_.lastsuccesssync -gt '02/01/2011'} | Sort-Object -Property DeviceType,Identity | Select-Object @{name="EmailAddress";expression={$_.Identity.ToString().Split("\")[0]}},DeviceType

Ok, now here is a quick way of doing the same thing but by using a filter. I recommend always using a filter to get your results. In this example we are filtering on EmailAddresses and only listing those people that have synced a device in the last 30 days. I spent a few hours trying to figure out how to best do this, and this is the best I could come up with. Please leave a comment if you know of a better way.

get-mailbox -ResultSize unlimited -Filter {EmailAddresses -like "*@email.com" } | ForEach {Get-ActiveSyncDeviceStatistics -Mailbox:$_.Identity  -ErrorAction SilentlyContinue}| where {$_.lastsuccesssync -gt '02/01/2011'} | Sort-Object -Property DeviceType,Identity | Select-Object @{name="EmailAddress";expression={$_.Identity.ToString().Split("\")[0]}},DeviceType | Export-Csv -Path:"c:\MobileDevices_email.com.csv"

Guest bloggers

Good evening, I have been speaking with co-workers about this blog and a few expressed interest in blogging about their day-to-day systems administration duties. In the near future you may see some posts from Steve Kremer. Steve is a co-worker of mine who deals with Active Directory, Citrix and Enterprise Messaging. Steve brings years of experience and a wide array of knowledge.

Active Directory Management with Active Administrator

I had a need the other day to restore a deleted OU from a Windows 2003 Active Directory.  This used to be such a big deal; requiring the AD, Server and Backup guys all working together.  Authoritative restores are such a pain in the rear, but Active Administrator by Scriptlogic has made this a non-issue.  We can pick an OU from one of the scheduled backups and re-animate the object with ease.  It almost makes you want to delete stuff just so you can restore it.

The product is a little pricey, but it only takes one or two restores for it to pay for itself.  I would highly recommend this product to anyone responsible for managing active directory.

Here is a link to a case study I was interviewed for several months ago: