Optimize Performance of AD DS Queries via PowerShell

Summary: Guest blogger, Matt Tisdale, talks about using the Measure-Command cmdlet to optimize an AD DS query.

Microsoft Scripting Guy, Ed Wilson, is here. I love to attend events where I can meet new people and get reacquainted with those I have previously met. I especially love meeting people and hearing how they use Windows PowerShell. One such person I met at TechEd North America in New Orleans is Matt Tisdale. I really had a nice conversation with Matt, and when we got home I received an email from him sharing three blog posts that he has written to help his coworkers. He was encouraged to share these with us based on my conversation with him. And without further ado, I will turn it over to Matt…

Today we are going to briefly discuss two items. The main item we are going to discuss is learning how to measure the run time of any Windows PowerShell command. As we look at an example of measuring execution time, we will also learn a couple things about how to query Active Directory more efficiently.

In a Windows PowerShell class I recently taught, I showed students how to find all user accounts for “regular” employees and then display their name, employeeType, and department attributes. Here is the command I used:

Get-ADUser -Filter ’employeeType -eq “regular”‘ -SearchBase “OU=people,DC=company,DC=com” -Properties employeeType,department

After running this command, a student asked the following questions:

  • What is the purpose of using -SearchBase? This command works just fine for me without using this parameter, and it becomes a shorter command to type.
  • Why are you listing specific property names? If I enter -Properties *, it returns all the available properties, and I can find what I need.

Both of these are great questions, and the short answer is that we use these parameters to make the search as efficient as possible. So how can we prove one search is more efficient than another? One of the simplest ways is to see how long each one takes and use the fastest one. To do this, we use a cmdlet called Measure-Command.

This cmdlet is used to measure exactly how long it takes for any given Windows PowerShell command to run. The basic command syntax is Measure-Command -Expression { enter some command here }. For example, if we want to see how long it takes the command Get-Service to run, we would use this syntax: Measure-Command -Expression { Get-Service }.

If you run this, you will notice the only output will be details about how long it took this command to run. You will not see any of the normal results from Get-Service. This will be true for any command you enter in the -Expression parameter of Measure-Command. Only details about the execution time will be shown, not the results of the command you are measuring. Now let’s look at using Measure-Command to answer the previous questions about Get-ADUser.

First, we want to find all “regular” employees without using a specific search base, and we want to return all properties instead of only the three specific ones we really need.

Measure-Command -Expression { Get-ADUser -Filter ’employeetype -eq “regular”‘ -Properties * }

I ran this command and the results are:

Days : 0
Hours : 0
Minutes : 2
Seconds : 44
Milliseconds : 104
Ticks : 1641047740
TotalDays : 0.00189936081018519
TotalHours : 0.0455846594444444
TotalMinutes : 2.73507956666667
TotalSeconds : 164.104774
TotalMilliseconds : 164104.774

Two minutes and 44 seconds seems like a long time to wait for this information.

Now we will try using -SearchBase to search only the “people” OU instead of the entire domain. Notice that we are still using -Properties * to return all available user properties.

Measure-Command -Expression { Get-ADUser -Filter ’employeetype -eq “regular”‘ -SearchBase “OU=people,DC=company,DC=com” -Properties * }

Minutes : 2
Seconds : 25

This is a little faster, but still seems to take too long. Searching a lower-level OU limits the number of user objects in scope, and therefore, it takes less time to return data. In my environment, the “people” OU contains all normal user accounts used by employees to sign in. Other types of accounts are located somewhere else.

Now we will only return the specific properties we require instead of all available attributes. Notice we are keeping the -SearchBase parameter because this helps efficiency.

Measure-Command -Expression { Get-ADUser -Filter ’employeetype -eq “regular”‘ -SearchBase “OU=people,DC=company,DC=com” -Properties employeeType,department,dvnDistrict }

Minutes : 0
Seconds : 13

Notice the significant improvement? By returning only the specific properties we require, we are reducing the runtime, amount of memory consumption on the workstation, and amount of resource consumption on the domain controller. This is a win-win all around.

In Windows PowerShell, there are many cases where tasks can be performed by using different commands and parameter combinations. When you are looking for the most efficient way to perform tasks, Measure-Command is a great tool to have in your toolbox. It sure beats using a stop watch.


Thank you for sharing, Matt. Join us tomorrow for some more words of wisdom from Matt.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy


Comments (2)

  1. What Makes a Fast Active Directory Query?


    Creating More Efficient Microsoft Active Directory-Enabled Applications


  2. Perhaps also worth mentioning is the effect of filtering early and limiting resultsets on memory usage.

Skip to main content