AD Cmdlets and Wildcards

Here’s a quick test – write down your answers:

Which of the following Active Directory cmdlets will execute faster?
a). Get-QADUser
b). Get-QADUser -Name q*t
c). No significant difference

You wrote down the answer, right?

Let’s see what is the actual thinking behind the problem.

The difference between the commands in the answers is that the first one gets the whole list while the second one applies a wildcard to limit the scope. You would expect that if you do the filtering the speed will go up. However, this is not always the case because if the cmdlets leave it to PowerShell to do the filtering it is actually being done on the client side after all the data has been retrieved. So for a lot of cmdlets out there the answer would be c). No significant difference (try get-process and get-process *notepad*).

Luckily for AD cmdlets the answer is indeed b). filtering makes execution way faster. And the reason is that by default AD cmdlets try to use the wildcards you supply in their LDAP queries against AD. Thus, all filtering is done by domain controller (and AD is optimized for such queries) and the client only retrieves the fraction of objects it needs.

In real-life environments with thousands (or tens or hundreds thousands) AD objects this can be a huge performance difference.

Great job by the AD cmdlets team!


P.S. To check the speed I was executing the same cmdlet 10 times, killed the output so it would not affect performance, and used get-time to check time:

PS C:\> $a = get-date
PS C:\> for($i=1; $i -le 10; $i++){$tmp=get-process;}
PS C:\> (get-date) - $a

Seconds : 0
Milliseconds : 31

PS C:\> $a = get-date
PS C:\> for($i=1; $i -le 10; $i++){$tmp=get-process *notepad*;}
PS C:\> (get-date) - $a

Seconds : 0
Milliseconds : 31

PS C:\> $a = get-date
PS C:\> for($i=1; $i -le 10; $i++){$tmp=get-QADUser;}
PS C:\> (get-date) - $a

Seconds : 41
Milliseconds : 375

PS C:\> $a = get-date
PS C:\> for($i=1; $i -le 10; $i++){$tmp=get-QADUser -Name q*t;}
PS C:\> (get-date) - $a

Seconds : 0
Milliseconds : 250

P.P.S. The only drawback to that is that some of PowerShell wildcard flexibility gets lost. If you need more than just * (e.g. a range like [p-r]*t) you’ll need to use PowerShell filtering because LDAP is not capable of such complex wildcards. Thus, you’ll need to use syntax like: Get-QADUser -Name [p-r]*t -WildcardMode PowerShell – and get the flexibility at the price of performance.

P.P.P.S. It looks like Exchange cmdlets are using the same approach to optimize for speed. However, I could not find a way to use rich PowerShell wildcard syntax with them at all.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

My Recent Tweets


The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

April 2007
« Mar   May »

%d bloggers like this: