Steve Goodman's Exchange Blog
23Sep/1041

Balancing the number of mailboxes across Exchange 2010 and 2007 databases

Introduction

In Exchange 2010, you now have the option to allow mailboxes to be automatically distributed across databases. However, the algorithm used simply randomly allocates the new mailbox to your chosen databases - rather than ensuring the mailbox count is balanced, and doesn't do anything about re-distributing mailboxes if you add new databases.

To help with this, and of course to help with any situation where you want to balance the number of mailboxes across a set of databases, I've written a simple script that help with moving mailboxes to balance out your databases.

Using Generate-DBBalanceScript.ps1

There's nothing too complicated about the script- it doesn't balance based on mailbox size (a future version), but simply creates a script with Move-Mailbox or New-MoveRequest  commands that once complete, balances based on mailbox counts across the databases. You pass it the results of a Get-MailboxDatabase command, along with an output file that will contain the Mailbox move commands.

First of all, lets see it in action:

Of course, my example was the simplest - across all databases. Here's a few examples including the one above, and some others that show how to drill down to databases on specific servers:

Example One - Generate a move file based on all Exchange 2010 Databases:

.\Generate-BalanceMoveRequests.ps1 -DBs (Get-MailboxDatabase) -OutputPowershellFile .\moves.ps1

Example Two - Generate a move file based on  Exchange 2010 Databases located on a single server "servername":

$o=Get-MailboxDatabase -Server servername
.\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false

Example Three - Generate a move file based on  Exchange 2007 Databases located on two servers, "serverone" and "servertwo":

$o=Get-MailboxDatabase | where {$_.Server -eq "serverone" -or $_.Server -eq "servertwo"}
.\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false
Download Generate-DBBalanceScript.ps1

You can download Generate-DBBalanceScript.ps1 here or view the script below.

Hope this helps!

<#
    .SYNOPSIS
    Generates a Powershell file containing Mailbox Move Cmdlets to help balance mailbox databases, based on mailbox count, not size.
    .DESCRIPTION
    Using a list of Databases, works out the average number of mailboxes there should be per DB, then generates move commands to run seperately.
   
    By Steve Goodman
    .PARAMETER DBs
    Databases to use
    The result of a Get-MailboxDatabase cmdlet. Eg. (Get-MailboxDatabase -Server name)
    .PARAMETER OutputPowershellFile
    The filename to write, for example C:\output.ps1 or .\output.ps1
    .PARAMETER Exchange2010
    By default, true. Set to $false to generate Exchagne2007 move-mailbox commands
    .EXAMPLE
    Generate a move file based on all Exchange 2010 Databases
     .\Generate-BalanceMoveRequests.ps1 -DBs (Get-MailboxDatabase) -OutputPowershellFile .\moves.ps1
    .EXAMPLE
    Generate a move file based on  Exchange 2007 Databases located on a single server "servername"
    $o=Get-MailboxDatabase -Server servername
    .\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false
    .EXAMPLE
    Generate a move file based on  Exchange 2007 Databases located on two servers, "serverone" and "servertwo"
    $o=Get-MailboxDatabase | where {$_.Server -eq "serverone" -or $_.Server -eq "servertwo"}
    .\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false
   
    #>

param(
    [parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false,HelpMessage="Mailbox database object")][array]$DBs,
    [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$false,HelpMessage="Filename for output Powershell script")][string]$OutputPowershellFile,
    [parameter(Position=2,Mandatory=$false,ValueFromPipeline=$false,HelpMessage="Is this for Exchange 2010")][bool]$Exchange2010=$true
    )

# Check for Exchange cmdlets
if (!(Get-Command Get-MailboxDatabase -ErrorAction SilentlyContinue))
{
    throw "Exchange Cmdlets not available";
}
# Check input object
if ($DBs[0].GetType().Name -ne "MailboxDatabase")
{
    throw "Object is not an array of mailbox databases"
}
if ($DBs.Count -eq 1)
{
    throw "You can't balance a single database";
}

# Check file does not exist
if ((Test-Path $OutputPowershellFile))
{
    throw "File $($OutputPowershellFile) already exists";
}

# Initialise file
"# Mailbox Mail Powershell Script File, generated $(date)`r`n"|Out-File -FilePath $OutputPowershellFile -NoClobber
if (!(Test-Path $OutputPowershellFile))
{
    throw "Could not write to $($OutputPowershellFile)";
}

# Initialise Variables
[int]$TotalMailboxes=0; # Total Mailboxes
[int]$BalancedCount=0; # Balanced Number of Mailboxes per DB
[array]$DBCounters=@(); # Array with DB Id, Mailbox Count and Mailbox listing
[array]$UA_DBCounters=@(); # Under allocated list from above, populated later
[array]$OA_DBCounters=@(); # Over allocated list from above, populated later
[array]$PA_DBCounters=@(); # Perfectly allocated list from above, populated later
[string]$Output=""; # Variable to write output text to

# Gather initial mailbox counts
Write-Host "Gathering Mailbox Counts"
for ($i = 0; $i -lt $DBs.Count; $i++)
{
    Write-Progress -activity "Gathering Mailbox Counts" -status "Processing Database $($DBs[$i].Identity)" -PercentComplete (($i / $DBs.Count)  * 100)
    $Mailboxes = (Get-Mailbox  -Database $DBs[$i].Identity -ResultSize Unlimited | select Identity)
    $DBCounters=$DBCounters+1;
    $DBCounters[$DBCounters.Count-1] = New-Object Object
    $DBCounters[$DBCounters.Count-1] | Add-Member NoteProperty Database $DBs[$i].Identity    
    $DBCounters[$DBCounters.Count-1] | Add-Member NoteProperty Total $Mailboxes.Count
    $DBCounters[$DBCounters.Count-1] | Add-Member NoteProperty Mailboxes $Mailboxes
    $TotalMailboxes+=$Mailboxes.Count
}
Write-Progress -Activity "Gathering Mailbox Counts" -Completed -Status "Completed"
Write-Host "DB Counts are as follows:"
$DBCounters|Select Database,Total
$BalancedCount = $TotalMailboxes / $DBs.Count
Write-Host "Found $($TotalMailboxes) mailboxes across $($DBs.Count) databases. Aiming for $($BalancedCount) mailboxes per database."

Write-Host "Sorting Databases into over, under and perfectly allocated."
# Sort DBs into under-allocated, over-allocated and perfectly allocated
for ($i = 0; $i -lt $DBCounters.Count; $i++)
{
    Write-Progress -activity "Sorting Databases into over, under and perfectly allocated" -status "Processing Database $($DBCounters[$i].Database)" -PercentComplete (($i / $DBCounters.Count)  * 100)
    if ($DBCounters[$i].Total -lt $BalancedCount)
    {
        $UA_DBCounters=$UA_DBCounters+1;
        $UA_DBCounters[$UA_DBCounters.Count-1] = $DBCounters[$i];
    } elseif ($DBCounters[$i].Total -gt $BalancedCount) {
        $OA_DBCounters=$OA_DBCounters+1;
        $OA_DBCounters[$OA_DBCounters.Count-1] = $DBCounters[$i];
    } else {
        $PA_DBCounters=$PA_DBCounters+1;
        $PA_DBCounters[$PA_DBCounters.Count-1] = $DBCounters[$i];
    }
}
Write-Progress -activity "Sorting Databases into over, under and perfectly allocated" -Completed -Status "Completed"

Write-Host "Found $($OA_DBCounters.Count) over, $($UA_DBCounters.Count) under and $($PA_DBCounters.Count) perfectly allocated";
# Make move list
Write-Host "Generating Powershell File '$($OutputPowershellFile)' to Balance DBs."
for ($i = 0; $i -lt $OA_DBCounters.Count; $i++)
{
    Write-Progress -activity "Generating Powershell File '$($OutputPowershellFile)' to Balance DBs" -status "Processing Database $($OA_DBCounters[$i].Database)" -PercentComplete (($i / $OA_DBCounters.Count)  * 100)
    # Get the mailbox list
    [array]$OA_Mailboxes = $OA_DBCounters[$i].Mailboxes
    $UA_DBPointer=0;
    for ($j=$BalancedCount; $j -lt $OA_Mailboxes.Count; $j++)
    {
        # Move to next underallocated DB if required
        if ($UA_DBCounters[$UA_DBPointer].Total -ge $BalancedCount -and $UA_DBPointer -lt $UA_DBCounters.Count-1)
        {
                $UA_DBPointer++;
        }
        Write-Progress -activity "Generating move commands" -status "Processing $($OA_Mailboxes[$j].Identity)" -PercentComplete (($j / $OA_Mailboxes.Count)  * 100)
        # Generate a Powershell command for the move request
        if ($Exchange2010)
        {
            $Output+="New-MoveRequest -Identity '$($OA_Mailboxes[$j].Identity)' -TargetDatabase '$($UA_DBCounters[$UA_DBPointer].Database)' -Confirm:" + '$false' + "`r`n";
        } else {
            $Output+="Move-Mailbox -Identity '$($OA_Mailboxes[$j].Identity)' -TargetDatabase '$($UA_DBCounters[$UA_DBPointer].Database)'`r`n";
        }        
        $OA_DBCounters[$i].Total--; # Take one mailbox of the total on the overallocated DB
        $UA_DBCounters[$UA_DBPointer].Total++; # Add one mailbox tot the total of the current underallocated DB
       
       
    }
    Write-Progress -activity "Generating move commands" -Completed -Status "Completed"
}
Write-Progress -activity "Generating Powershell File '$($OutputPowershellFile)' to Balance DBs" -Completed -Status "Completed"
Write-Host "DB Counts will be as follows after executing $($OutputPowershellFile):"
$OA_DBCounters|Select Database,Total
$UA_DBCounters|Select Database,Total
$PA_DBCounters|Select Database,Total
Write-Host "Writing Powershell file '$($OutputPowershellFile)'"
$Output | Out-File -FilePath $OutputPowershellFile -NoClobber -Append

Related posts:

  1. How to report which Exchange mailboxes group members have full access to
  2. Scripted Shared Mailbox Creation on Exchange 2007/2010
  3. Using the Exchange 2010 SP1 Mailbox Export features for Mass Exports to PST files
  4. Writing Powershell scripts that target Exchange 2007 and 2010
  5. Sync a text file to an Exchange distribution group
Comments (41) Trackbacks (0)
  1. This script looks like it’ll sort out a number of problems we’re having with the distribution of our mailboxes across our storage groups. We’ve got a SCR clustered Exchange 2007 environment and I’ve tried running your script but it fails immediately with the following error:

    Unable to find type [parameter(Position=0,Mandatory=$true,ValueFromPipeline=$fa
    lse,HelpMessage="Mailbox database object")]: make sure that the assembly contai
    ning this type is loaded.

    To run the script I first typed:
    $o=Get-MailboxDatabase -Server servername
    followed by:
    .\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false

    Apologies, I’m far from a powershell expert – more like a novice! Any help you could provide though would be great as this script is exactly the answer to our problems!

    Thanks in advance,
    Sam

    • I’ll take a look – I did test on 2007 but will have another go. I tested on Powershell 2.0 so wonder if that is the issue..

      Steve

      • Hi Steve,
        Many thanks! I’ll wait to hear from you – let me know if you need any more information about our environment etc. though.

        Sam

      • Hiya,

        It looks like it’s a Powershell 1.0 issue – as a quick hack try the following:

        Change the first bit of the script up until “# Check for Exchange cmdlets” to:

        param($DBs,$OutputPowershellFile,$Exchange2010=$true)

        # Check for Exchange cmdlets

        This takes out some of the get-help compatibility and prompting for values, but assuming you put the right values (like you did above) it looks like it works fine on Win 2003 Ent + Exchange 2007 SP3 + Powershell 1.0.

        Steve

  2. Hi Steve,
    It’s working!!! That did the trick, thanks!

    I’m planning to split the move script that’s generated into blocks of 100 mailboxes as we have around 1000 mailboxes to move (our old Exchange admin decided to tell the people creating mailboxes to create them all in one storage group for some reason leaving us with one SG with over 1800 mailboxes!!). Obviously we’ve got a fair amount of work to do to tell these users when we’ll be moving their mailboxes and to then schedule the appropriate scripts to run.

    Thanks so much for your help with this – it’s saved us a huge amount of work!
    Sam

  3. Hi Steve,
    Sorry, one last question: Is there a way to tell the script to exclude one of the Storage Groups when balancing the mailboxes across the DBs? We need to exlude the First Storage Group completely as there is limited disk space available for this and it is only used for service mailboxes etc.

    Thanks again,
    Sam

  4. Hi Steve,
    Thanks again – this worked, although with a slight modification:

    I changed it to:

    $o=Get-MailboxDatabase -server mkt-mbx01 | where-object {$_.name -ne “Mailbox Database”}

    This excludes the first storage group’s mailbox DB successfully from the calculations for balancing the mailboxes.

    Thanks once again for all your help – I’m learning more from you about Powershell scripting than I have from numerous books!

    Sam

  5. interesting, thanks

  6. I just signed up to your blogs rss feed. Will you post more on this subject?

  7. Not really good with the scripting thing but i need to do this load balancing across top 2 exchange 2007 servers with 4 storage groups each. How would i achieve this using your scripts

    • Hi Lamont,

      You would use Example three from above:

      $o=Get-MailboxDatabase | where {$_.Server -eq “serverone” -or $_.Server -eq “servertwo”}
      .\Generate-BalanceMoveRequests.ps1 -DBs $o -OutputPowershellFile moves07.ps1 -Exchange2010:$false

      Also, if you are using Powershell V1 and not Powershell V2 you will need to do this:

      Change the first bit of the script up until “# Check for Exchange cmdlets” to:

      param($DBs,$OutputPowershellFile,$Exchange2010=$true)

      # Check for Exchange cmdlets

      Steve

  8. Hi Steve,

    I enjoy reading your blog. I’m trying to come up with a script to do something similar to this one. Our helpdesk creates all new mailboxes in one SG (Staging) and then we spread them out among the other SG’s. to balance them. I would like to automate this task to move them to the least populated SG’s, similar to what you are doing with these scripts.

  9. Hi Steve,

    Great script! Is it possible to get the reverse, balance mailbox databases based on mailbox size not count for Exchange 2010?

    Cheers,
    Alan

    • Hi Alan,

      Glad you like it. I’d been thinking the same thing – it would be useful to balance based on size instead of mailbox numbers.

      Balancing on mailbox numbers has a basis in each DB’s underlying LUN being fully provisioned to be able to support full quotas for each mailbox. However another approach could be to add storage and additional DBs as mailboxes grow toward their quotas, and this would require re-balancing the databases based on size as you suggest.

      So – It’s added to my to-do list :-)

      Steve

  10. Hi,

    thanks for your script . I tried and it work but there is a small issue while running moves.ps1 in exchange 2007 environments . so issue is that for every mailbox move it prompts for yes or No input. so can you help me with that so that all i can do without changing anything in moves.ps1. or there is any way to add -confirm :$false in each line while generating the script.

  11. Hi Steve

    Great script. Any news on a script that are able to relocate based on size :)

    Thanks,
    Peter

    • I will have to do that soon, won’t I.. And take into account archive mailboxes, too. It is on my list – the new year has been pretty busy so far so just getting a handle again on the blog :-)

      Steve

  12. Hi Steve,

    I did notice one issue when the script generates the list of moves. Currently it uses the Identity of each user which seems to the OU plus CN. We have some users with parenthesis in the name of the OU where their mailbox resides which causes the script to fail with the following error:

    The term ‘Sales’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spell
    ing of the name, or if a path was included, verify that the path is correct and try again.
    At C:\Tech\Scripts\PowerShell\dbmoves.ps1:41 char:83
    + New-MoveRequest -Identity ‘domain.com/Corp/Users/HQ (Sales <<<< )/Smith, Tom' -TargetDat
    abase 'DB15'
    + CategoryInfo : ObjectNotFound: (Sales:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Is there any way to have it output the user name via PrimarySMTPAddress in the move script?

    Thanks,

    -Devon

  13. Hi Steve,

    Do you have any information on how to balance the databases based on mailbox size and only on a select list of databases? Thanks for all you do.

  14. Hi Steve,
    We have 6 databases in all, but they are in pairs. Just for an example say there are two on Solid state drives, two on Fiber channel 15K and 2 on SATA. What would I have to do to get your script to balance mailboxes across two server but just within two specific databases?

    In case that isn’t completely clear here is an example:
    Server 1 databases: SS-Server1-DB1, FC-Server1-DB1, SATA-Server1-DB1
    Server 2 databases: SS-Server2-DB1, FC-Server2-DB1, SATA-Server2-DB1

    I would like to balance the mailboxes between the two SS* databases, then the mailboxes between the two FC* databases, and finally the mailboxes between the two SATA* databases.

    Thanks for your assistance.
    Greg

  15. Steve,

    This is a fine piece of work. I am so close to getting it working but keep hitting some limit. Below is output that I get from any Exchange 2010 server where I run this. We have a 12 node DAG that just got 4 new nodes introduced and I’m trying to balance those 19705 accounts across 12 servesr rather than the current 8. There are 96 new databases and the script targets 75 per db which makes sense. What is perplexing is that the file it generates 7103 New-MoveRequests but ignores 58 databases and as you can see below it overloads 36 db’s. Have I hit some limit? Any help would be appreciated.

    —————————————————————————————————————–
    Found 19705 mailboxes across 264 databases. Aiming for 75 mailboxes per database.
    Sorting Databases into over, under and perfectly allocated.
    Found 168 over, 96 under and 0 perfectly allocated
    Generating Powershell File ‘.\moves6.ps1′ to Balance DBs.
    DB Counts will be as follows after executing .\moves6.ps1:
    EXSRV09DB01 — 75
    EXSRV09DB02 — 75
    EXSRV09DB03 — 75
    EXSRV10DB01 — 75
    EXSRV10DB02 — 75
    EXSRV10DB03 — 75
    EXSRV11DB01 — 75
    EXSRV11DB02 — 75
    EXSRV11DB03 — 75
    EXSRV12DB01 — 75
    EXSRV12DB02 — 75
    EXSRV12DB03 — 75
    EXSRV01DB01 — 75
    EXSRV01DB02 — 75
    EXSRV01DB03 — 75
    EXSRV01DB04 — 75
    EXSRV09DB04 — 75
    EXSRV09DB05 — 75
    EXSRV09DB06 — 75
    EXSRV09DB07 — 75
    EXSRV09DB08 — 75
    EXSRV09DB09 — 75
    EXSRV10DB04 — 75
    EXSRV10DB05 — 75
    EXSRV10DB06 — 75
    EXSRV10DB07 — 75
    EXSRV10DB08 — 75
    EXSRV10DB09 — 75
    EXSRV11DB04 — 75
    EXSRV11DB07 — 75
    EXSRV11DB05 — 75
    EXSRV11DB06 — 75
    EXSRV11DB09 — 75
    EXSRV11DB08 — 75
    EXSRV12DB06 — 75
    EXSRV12DB05 — 75
    EXSRV12DB04 — 75
    EXSRV12DB07 — 75
    EXSRV12DB08 — 75
    EXSRV12DB09 — 75
    EXSRV01DB06 — 75
    EXSRV01DB10 — 75
    EXSRV01DB12 — 75
    EXSRV01DB09 — 75
    EXSRV01DB07 — 75
    EXSRV01DB08 — 75
    EXSRV01DB05 — 75
    EXSRV01DB11 — 75
    EXSRV09DB10 — 75
    EXSRV09DB11 — 75
    EXSRV09DB12 — 75
    EXSRV09DB13 — 75
    EXSRV09DB14 — 75
    EXSRV09DB15 — 75
    EXSRV09DB16 — 75
    EXSRV09DB17 — 75
    EXSRV09DB18 — 75
    EXSRV10DB10 — 75
    EXSRV10DB11 — 75
    EXSRV10DB12 — 75
    EXSRV10DB13 — 75
    EXSRV10DB14 — 75
    EXSRV10DB15 — 75
    EXSRV10DB16 — 75
    EXSRV10DB17 — 75
    EXSRV10DB18 — 75
    EXSRV11DB11 — 75
    EXSRV11DB18 — 75
    EXSRV11DB13 — 75
    EXSRV11DB12 — 75
    EXSRV11DB10 — 75
    EXSRV11DB16 — 75
    EXSRV11DB17 — 75
    EXSRV11DB15 — 75
    EXSRV11DB14 — 75
    EXSRV12DB10 — 75
    EXSRV12DB11 — 75
    EXSRV12DB12 — 75
    EXSRV12DB13 — 75
    EXSRV12DB14 — 75
    EXSRV12DB15 — 75
    EXSRV12DB16 — 75
    EXSRV12DB17 — 75
    EXSRV12DB18 — 75
    EXSRV01DB19 — 75
    EXSRV01DB22 — 75
    EXSRV01DB15 — 75
    EXSRV01DB14 — 75
    EXSRV01DB23 — 75
    EXSRV01DB17 — 75
    EXSRV01DB16 — 75
    EXSRV01DB21 — 75
    EXSRV01DB20 — 75
    EXSRV01DB13 — 75
    EXSRV01DB18 — 75
    EXSRV01DB24 — 75
    EXSRV02DB01 — 75
    EXSRV02DB02 — 75
    EXSRV02DB03 — 75
    EXSRV02DB04 — 75
    EXSRV02DB05 — 75
    EXSRV02DB06 — 75
    EXSRV02DB07 — 75
    EXSRV02DB08 — 75
    EXSRV02DB09 — 75
    EXSRV02DB10 — 75
    EXSRV02DB11 — 75
    EXSRV02DB12 — 75
    EXSRV02DB13 — 75
    EXSRV02DB14 — 75
    EXSRV02DB15 — 75
    EXSRV02DB16 — 75
    EXSRV02DB17 — 75
    EXSRV02DB18 — 75
    EXSRV02DB19 — 75
    EXSRV02DB20 — 75
    EXSRV02DB21 — 75
    EXSRV02DB22 — 75
    EXSRV02DB23 — 75
    EXSRV02DB24 — 75
    EXSRV03DB01 — 75
    EXSRV03DB02 — 75
    EXSRV03DB03 — 75
    EXSRV03DB04 — 75
    EXSRV03DB05 — 75
    EXSRV03DB06 — 75
    EXSRV03DB07 — 75
    EXSRV03DB08 — 75
    EXSRV03DB09 — 75
    EXSRV03DB10 — 75
    EXSRV03DB11 — 75
    EXSRV03DB12 — 75
    EXSRV03DB13 — 75
    EXSRV03DB14 — 75
    EXSRV03DB15 — 75
    EXSRV03DB16 — 75
    EXSRV03DB17 — 75
    EXSRV03DB18 — 75
    EXSRV03DB19 — 75
    EXSRV03DB20 — 75
    EXSRV03DB21 — 75
    EXSRV03DB23 — 75
    EXSRV03DB22 — 75
    EXSRV03DB24 — 75
    EXSRV08DB01 — 75
    EXSRV08DB02 — 75
    EXSRV08DB03 — 75
    EXSRV08DB04 — 75
    EXSRV08DB05 — 75
    EXSRV08DB06 — 75
    EXSRV08DB07 — 75
    EXSRV08DB08 — 75
    EXSRV08DB09 — 75
    EXSRV08DB10 — 75
    EXSRV08DB11 — 75
    EXSRV08DB12 — 75
    EXSRV08DB13 — 75
    EXSRV08DB14 — 75
    EXSRV08DB15 — 75
    EXSRV08DB16 — 75
    EXSRV08DB17 — 75
    EXSRV08DB18 — 75
    EXSRV08DB19 — 75
    EXSRV08DB20 — 75
    EXSRV08DB21 — 75
    EXSRV08DB22 — 75
    EXSRV08DB23 — 75
    EXSRV08DB24 — 75
    EXSRV04DB01 — 75
    EXSRV04DB02 — 240
    EXSRV04DB03 — 238
    EXSRV04DB04 — 237
    EXSRV04DB05 — 236
    EXSRV04DB06 — 234
    EXSRV04DB07 — 233
    EXSRV04DB08 — 231
    EXSRV04DB09 — 230
    EXSRV04DB10 — 227
    EXSRV04DB11 — 225
    EXSRV04DB12 — 223
    EXSRV04DB13 — 220
    EXSRV04DB14 — 218
    EXSRV04DB15 — 216
    EXSRV04DB16 — 214
    EXSRV04DB17 — 212
    EXSRV04DB18 — 210
    EXSRV04DB19 — 208
    EXSRV04DB20 — 206
    EXSRV04DB21 — 204
    EXSRV04DB22 — 200
    EXSRV04DB23 — 195
    EXSRV04DB24 — 191
    EXSRV05DB06 — 185
    EXSRV05DB02 — 180
    EXSRV05DB08 — 176
    EXSRV05DB09 — 173
    EXSRV05DB04 — 169
    EXSRV05DB03 — 161
    EXSRV05DB05 — 155
    EXSRV05DB07 — 150
    EXSRV05DB01 — 143
    EXSRV05DB14 — 132
    EXSRV05DB12 — 112
    EXSRV05DB11 — 106
    EXSRV05DB10 — 90
    EXSRV05DB15 — 50
    EXSRV05DB16
    EXSRV05DB17
    EXSRV05DB13
    EXSRV05DB18
    EXSRV05DB19
    EXSRV05DB20
    EXSRV05DB24
    EXSRV05DB21
    EXSRV05DB22
    EXSRV05DB23
    EXSRV07DB03
    EXSRV07DB01
    EXSRV07DB02
    EXSRV07DB04
    EXSRV07DB05
    EXSRV07DB06
    EXSRV07DB07
    EXSRV07DB08
    EXSRV07DB09
    EXSRV07DB10
    EXSRV07DB11
    EXSRV07DB12
    EXSRV07DB13
    EXSRV07DB14
    EXSRV07DB15
    EXSRV07DB16
    EXSRV07DB17
    EXSRV07DB18
    EXSRV07DB19
    EXSRV07DB20
    EXSRV07DB21
    EXSRV07DB22
    EXSRV07DB24
    EXSRV07DB23
    EXSRV06DB01
    EXSRV06DB02
    EXSRV06DB03
    EXSRV06DB04
    EXSRV06DB05
    EXSRV06DB06
    EXSRV06DB07
    EXSRV06DB08
    EXSRV06DB09
    EXSRV06DB10
    EXSRV06DB11
    EXSRV06DB12
    EXSRV06DB13
    EXSRV06DB14
    EXSRV06DB16
    EXSRV06DB20
    EXSRV06DB17
    EXSRV06DB18
    EXSRV06DB19
    EXSRV06DB15
    EXSRV06DB21
    EXSRV06DB22
    EXSRV06DB23
    EXSRV06DB24
    Writing Powershell file ‘.\moves.ps1′
    —————————————————————————————————————–

    • Hiya,

      I’ve not tried the script on that many mailboxes and wouldn’t recommend running that many move requests in one go (though, I must admit the script shouldn’t have went wrong).

      Do you have any better success if you limit the number of databases, perhaps balancing 1-10, 11, 20 etc?

      Steve

  16. Steve,

    Thanks for getting back to me. How would I limit? I am excluding a dozen resource account databases. I was trying to figure out a way to try and have it see half of our server and do the balancing against it only. I guess the challenge is how to omit some and include only others?

  17. Steve,

    Stretching my weak powershell skills to their limits I managed to do all the inclusions/exclusions and divide everything in half. Half of my existing servers coupled with half the new in each new set. Same results but only half as much :-) Same deal. It excludes most, not all of the new databases. We’ve done get-mailboxdatabase |fl side by side between working and non-working db’s and their identical. All databases were created with standard script as you can imagine what a chore it would be manually.

    Any ideas? Thanks for your help.

    Found 9636 mailboxes across 132 databases. Aiming for 73 mailboxes per database.
    Sorting Databases into over, under and perfectly allocated.
    Found 84 over, 48 under and 0 perfectly allocated
    Generating Powershell File ‘.\moves.ps1′ to Balance DBs.
    DB Counts will be as follows after executing .\moves.ps1

  18. Steve,

    I quarted it down to 72 databases and have the same strange results. The balacing is going against 3 servers, 2 old and one new. Results below:

    Found 5399 mailboxes across 72 databases. Aiming for 75 mailboxes per database.
    Sorting Databases into over, under and perfectly allocated.
    Found 48 over, 24 under and 0 perfectly allocated
    Generating Powershell File ‘.\moves1-2to6.txt’ to Balance DBs.
    DB Counts will be as follows after EXSRVecuting .\moves1-2to6.txt:
    EXSRV01DB01 — 75
    EXSRV01DB02 — 75
    EXSRV01DB03 — 75
    EXSRV01DB04 — 75
    EXSRV01DB06 — 75
    EXSRV01DB10 — 75
    EXSRV01DB12 — 75
    EXSRV01DB09 — 75
    EXSRV01DB07 — 75
    EXSRV01DB08 — 75
    EXSRV01DB05 — 75
    EXSRV01DB11 — 75
    EXSRV01DB19 — 75
    EXSRV01DB22 — 75
    EXSRV01DB15 — 75
    EXSRV01DB14 — 75
    EXSRV01DB23 — 75
    EXSRV01DB17 — 75
    EXSRV01DB16 — 75
    EXSRV01DB21 — 75
    EXSRV01DB20 — 75
    EXSRV01DB13 — 75
    EXSRV01DB18 — 75
    EXSRV01DB24 — 75
    EXSRV02DB01 — 75
    EXSRV02DB02 — 75
    EXSRV02DB03 — 75
    EXSRV02DB04 — 75
    EXSRV02DB05 — 75
    EXSRV02DB06 — 75
    EXSRV02DB07 — 75
    EXSRV02DB08 — 75
    EXSRV02DB09 — 75
    EXSRV02DB10 — 75
    EXSRV02DB11 — 75
    EXSRV02DB12 — 75
    EXSRV02DB13 — 75
    EXSRV02DB14 — 75
    EXSRV02DB15 — 75
    EXSRV02DB16 — 75
    EXSRV02DB17 — 75
    EXSRV02DB18 — 75
    EXSRV02DB19 — 75
    EXSRV02DB20 — 75
    EXSRV02DB21 — 75
    EXSRV02DB22 — 75
    EXSRV02DB23 — 75
    EXSRV02DB24 — 75
    EXSRV06DB01 — 75
    EXSRV06DB02 — 118
    EXSRV06DB03 — 116
    EXSRV06DB04 — 114
    EXSRV06DB05 — 111
    EXSRV06DB06 — 109
    EXSRV06DB09 — 107
    EXSRV06DB07 — 105
    EXSRV06DB08 — 103
    EXSRV06DB10 — 101
    EXSRV06DB11 — 98
    EXSRV06DB12 — 96
    EXSRV06DB13 — 93
    EXSRV06DB14 — 90
    EXSRV06DB16 — 88
    EXSRV06DB20 — 86
    EXSRV06DB17 — 83
    EXSRV06DB18 — 77
    EXSRV06DB19 — 27
    EXSRV06DB15
    EXSRV06DB21
    EXSRV06DB22 — 2
    EXSRV06DB23
    EXSRV06DB24
    Writing Powershell file ‘.\moves1-2to6.txt’

  19. Steve,

    Sorry I won’t bombard with anymore information after this. I reduced this down to 2 servers, old to new with 18 databases balancing to 24. Still strange results. Any thoughts?

    .\Generate-DBBalanceScript.ps1 -DBs $o -OutputPowershellFile .\moves9to4.2.txt
    Gathering Mailbox Counts
    DB Counts are as follows:

    Database Total
    ———— —–
    EXSRV09DB01 — 122
    EXSRV09DB02 — 122
    EXSRV09DB03 — 120
    EXSRV09DB04 — 118
    EXSRV09DB05 — 120
    EXSRV09DB06 — 109
    EXSRV09DB07 — 118
    EXSRV09DB08 — 115
    EXSRV09DB09 — 117
    EXSRV09DB10 — 112
    EXSRV09DB11 — 116
    EXSRV09DB12 — 106
    EXSRV09DB13 — 111
    EXSRV09DB14 — 99
    EXSRV09DB15 — 103
    EXSRV09DB16 — 108
    EXSRV09DB17 — 108
    EXSRV09DB18 — 103
    EXSRV04DB01 — 5
    EXSRV04DB02 — 5
    EXSRV04DB03 — 5
    EXSRV04DB04 — 5
    EXSRV04DB05 — 5
    EXSRV04DB06 — 5
    EXSRV04DB07 — 5
    EXSRV04DB08 — 5
    EXSRV04DB09 — 6
    EXSRV04DB10 — 5
    EXSRV04DB11 — 4
    EXSRV04DB12 — 5
    EXSRV04DB13 — 5
    EXSRV04DB14 — 4
    EXSRV04DB15 — 6
    EXSRV04DB16 — 3
    EXSRV04DB17 — 10
    EXSRV04DB21 — 10
    EXSRV04DB19 — 6
    EXSRV04DB23 — 11
    EXSRV04DB20 — 10
    EXSRV04DB22 — 3
    EXSRV04DB18 — 4
    EXSRV04DB24 — 3
    Found 2162 mailboxes across 42 databases. Aiming for 51 mailboxes per database.
    Sorting Databases into over, under and perfectly allocated.
    Found 18 over, 24 under and 0 perfectly allocated
    Generating Powershell File ‘.\moves9to4.2.txt’ to Balance DBs.
    DB Counts will be as follows after executing .\moves9to4.2.txt:
    EXSRV09DB01 — 51
    EXSRV09DB02 — 51
    EXSRV09DB03 — 51
    EXSRV09DB04 — 51
    EXSRV09DB05 — 51
    EXSRV09DB06 — 51
    EXSRV09DB07 — 51
    EXSRV09DB08 — 51
    EXSRV09DB09 — 51
    EXSRV09DB10 — 51
    EXSRV09DB11 — 51
    EXSRV09DB12 — 51
    EXSRV09DB13 — 51
    EXSRV09DB14 — 51
    EXSRV09DB15 — 51
    EXSRV09DB16 — 51
    EXSRV09DB17 — 51
    EXSRV09DB18 — 51
    EXSRV04DB01 — 51
    EXSRV04DB02 — 67
    EXSRV04DB03 — 67
    EXSRV04DB04 — 66
    EXSRV04DB05 — 65
    EXSRV04DB06 — 64
    EXSRV04DB07 — 64
    EXSRV04DB08 — 63
    EXSRV04DB09 — 62
    EXSRV04DB10 — 61
    EXSRV04DB11 — 61
    EXSRV04DB12 — 60
    EXSRV04DB13 — 59
    EXSRV04DB14 — 58
    EXSRV04DB15 — 57
    EXSRV04DB16 — 56
    EXSRV04DB17 — 55
    EXSRV04DB21 — 54
    EXSRV04DB19 — 52
    EXSRV04DB23 — 51
    EXSRV04DB20 — 41
    EXSRV04DB22 — 3
    EXSRV04DB18 — 4
    EXSRV04DB24 — 3
    Writing Powershell file ‘.\moves9to4.2.txt’

  20. Steve, did you ever update this script to balance mailboxes based on size? We’ve got to divide a single database into 5 and we want to balance the size of the database.

  21. Steve, do you know if a script can be created to rebalance the DAG in 2010?
    If I have 3 servers, 3 databases and have copies of each DB on each server, If I lose a server the DB all work but the third server is never used again when back online unless I manually balance them.

    • Hiya,

      A script is built into Exchange 2010 which performs this:

      Open Exchange Management Shell:

      cd $exscripts
      \RedistributeActiveDatabases.ps1 -DagName DAG -BalanceDbsByActivationPreference

      Steve

  22. Hey there Steve, I was wondering if you ever got a chance last year to write the Generate-BalancebySizeMoveRequests.ps1???? :)

    Chris


Leave a comment

(required)

No trackbacks yet.