Load balance new mailbox creation across multiple databases and servers using PowerShell

I needed a way to have new mailboxes be automatically distributed across a list of databases on multiple servers, and I recalled seeing a script somewhere.  The blog post with those details can be found here [no longer available].  As the author points out, it can take a long time to build the hash table, too long for my requirements.  For example, one of my longer queries builds the table for 9 databases with over 5000 mailboxes in 58 seconds.  That is just way too  long for someone to feed a user account into to get a mailbox created.

So I broke down the query being used to find where efficiency could be improved.  The Get-ExchangeServer cmdlet slows the script down and can be avoided altogether by feeding the server list directly into the Get-MailboxDatabase cmdlet.  Additionally, I discovered just how inefficient the Exchange cmdlets are.  I already knew they were based on running other cmdlets for targets servers across a WAN that return not a lot of data, but this reinforced those findings.

To get away from the Exchange cmdlets, I query AD directly by instantiating ADSI in .NET manually.  Instead of slowly building the hash table I just take the record count of the search results and populate the table entry at once.  This reduced the time to completion from 58 seconds to 24 seconds.  These findings are consistent across different database counts and mailbox totals: 60% reduction in time.  While still too long for my taste, it certainly is much better than before and is within reason for the people at my company that make use of the script.

Since my script encompasses more than just the load balancing part (I create a GUI form where the location for the mailbox is selected, which feeds a list of appropriate servers to the function), this is just the part that creates the hash table with the database counts and returns the database with the lowest count:

$mbxServers = @()
$mailboxcount = @{}
$domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = [ADSI]"GC://$($domain.Name)"
$mbxServers | %{Get-MailboxDatabase -server $_} | ?{$_.recovery -eq $FALSE} | %{
$filter = "(&(objectcategory=user)(homeMDB=" + ($_.DistinguishedName) + "))"
$search = new-Object System.DirectoryServices.DirectorySearcher($root,$filter)
$search.PropertiesToLoad.Add("homeMDB") | Out-Null
$result = $search.FindAll()
$mailboxcount["$($_.Identity)"] = $result.count
}
($mailboxcount.GetEnumerator() | sort value | select -first 1).key

3 thoughts on “Load balance new mailbox creation across multiple databases and servers using PowerShell

  1. Pingback: Get Mailbox Count per Database Efficiently | Diginomicon

  2. Hi Scott

    I have been looking for something to spread newly created mailboxes across exchange 2007 servers/stores but haven’t been very successful so far. Can you recall the blog post that you found the script at originally?

    Many thanks

    Keith

  3. At first I didn’t know why the link wasn’t a link anymore, but then I realized that the link checker I use on my site must have reported that it was no longer valid, so I had it remove the link. I did some searches to see if I could find the post that I was referencing. There was one that I thought might be it, but that blog no longer exists (WordPress hosting said that it had been deleted), which may very well have been the post. I will update the post to remove mentioning the source reference. What I can do is send you the full script that was used to balance new mailboxes in the 2007 environment at the time. If you are interested, let me know.

Leave a Reply

Your email address will not be published. Required fields are marked *

*