Estimate the time to complete seeding a mailbox database copy

Articles in the "Database seeding estimation" series

  1. Estimate the time to complete seeding a mailbox database copy [This article]
  2. Database seeding completion estimate script updated

Seeding a mailbox database copy, especially across a WAN, can take days to complete. The shell doesn’t give any indication of the time it will complete, though it does show a progress bar and the amount of data written. If you want to know when the seeding will actually finish, you can extrapolate this from the throughput of the seeding, dividing that into the amount of data remaining to be copied.

The throughput of a copy being seeded is available as a performance counter, as are the percentage complete and the amount written. Using this information I wrote a script to estimate the date and time the database seeding will complete. Because throughput can vary greatly from second to second, the default sample duration is 60 seconds. You can specify any number of seconds, choosing accuracy or impatience. Retrieving performance counters can take some time (not even counting any sampling you may do), so a progress indicator will indicate any time that is occurring. (Three separate queries for performance counters occur to provide the output.)

To run the script, provide a database copy and, optionally, a sample duration. The copy will be validated that it is being seeded, then the seeding throughput will be retrieved for 60 seconds or the duration you specified. Then the amount of data written so far is retrieved, comparing that to the total size of the database, so that the remaining amount can be determined. That amount is divided by the average throughput during the sample duration and calculating the time it will be done. Bear in mind that this calculation does not include the time to seed the content index or copy and replay transaction logs that have been generated since seeding began. The output will show the percentage of the database size that has been seeded thus far and the estimated date and time the seeding will complete.

You can copy the code below or download the script via the link.

  Get-DatabaseSeedingCompletion.zip (1.5 KiB)

<#
	.Synopsis
		Estimate time of completion for database seeding
	.Description
		Using a customizable sample duration of the seeding throughput for a database copy,
		the script estimates the date and time the seeding will complete.  This does
		not include the time to seed the content index or copy transaction logs that have
		been accruing since the seeding started.
	.Parameter Identity
		The identity of a database copy, using the format Database\Server.
	.Parameter SampleDuration
		The number of seconds (in one-second intervals) to monitor the seeding throughput
		in order to calculate the completion time.  The default is 60 seconds.
	.Example
		Get-DatabaseSeedingCompletion.ps1 -Identity database1\server2
	.Example
		Get-DatabaseSeedingCompletion.ps1 -Identity database2\serverA -SampleDuration 360
	.Notes
		Version: 1.1
		Date: 11/22/13
#>
param
	(
	[parameter(Mandatory=$true,Position=0)][string]$Identity,
	[parameter(Mandatory=$false,Position=1)][int]$SampleDuration = 60
	)
$database = $Identity.Substring(0,$Identity.IndexOf('\'))
$server = $Identity.Substring($Identity.IndexOf('\') + 1)
$showProgress = $true
while ($showProgress -eq $true)
	{
	Write-Progress -Activity 'Getting seeding progress percentage...' -Status 'Retrieving'
	$percentCompleteCounter = Get-Counter -ComputerName $server -Counter "\MSExchange Replica Seeder($database)\Database Seeding Progress %" -ErrorAction 'SilentlyContinue'
	$showProgress = $false
	Write-Progress -Activity 'Getting seeding progress percentage...' -Status 'Retrieving' -Completed
	}
if (-not($percentCompleteCounter))
	{
	Write-Warning -Message "$Identity is not currently being seeded."
	}
else
	{
	$percentComplete = $percentCompleteCounter.CounterSamples[0].CookedValue
	
	#Get seeding throughput
	$showProgress = $true
	while ($showProgress -eq $true)
		{
		Write-Progress -Activity 'Getting seeding throughput...' -Status "Sampling for $SampleDuration seconds"
		$kBytesWrittenPerSecondCounter = Get-Counter -ComputerName $server -Counter "MSExchange Replica Seeder($database)\Database Seeding Bytes Written (KB/sec)" -MaxSamples $SampleDuration
		$showProgress = $false
		Write-Progress -Activity 'Getting seeding throughput...' -Status 'Sampling' -Completed
		}
	$kBytesWrittenPerSecondAverage = $kBytesWrittenPerSecondCounter | ForEach-Object {$_.CounterSamples[0].CookedValue} | Measure-Object -Average | Select-Object -ExpandProperty Average
	if ($kBytesWrittenPerSecondAverage -eq 0)
		{
		Write-Warning -Message 'Cannot estimate completion time because throughput for the sampling period is 0 KB.'
		}
	else
		{
		#Get bytes written so far
		$showProgress = $true
		while ($showProgress -eq $true)
			{
			Write-Progress -Activity 'Getting seeding amount written so far...' -Status 'Retrieving'
			$kBytesWrittenCounter = Get-Counter -ComputerName $server -Counter "MSExchange Replica Seeder($database)\Database Seeding Bytes Written (KB)"
			$showProgress = $false
			Write-Progress -Activity 'Getting seeding amount written so far...' -Status 'Retrieving' -Completed
			}
		$kBytesWrittenValue = $kBytesWrittenCounter.CounterSamples[0].CookedValue
		
		#Get DB size to calculate remaining amount
		$dbSizeRaw = (Get-MailboxDatabase -Identity $database -Status).DatabaseSize
		if ($dbSizeRaw.GetType().Name -eq 'ByteQuantifiedSize') #Object type when using EMS
			{
			$dbSize = $dbSizeRaw.ToBytes()
			}
		else
			{ #Object type when using remoting is string
			$dbSize = [int64]($dbSizeRaw.Split("(")[1].Split()[0])
			}
		$KBRemaining = $dbSize/1KB - $kBytesWrittenValue
		$estimatedMinutesToCompletion = $KBRemaining/$kBytesWrittenPerSecondAverage/60
		$completionTime = (Get-Date).AddMinutes($estimatedMinutesToCompletion)
		$outputObject = "" | Select-Object -Property Identity,PercentComplete,'Throughput(MB/sec)',EstimatedCompletion
		$outputObject.Identity = $Identity
		$outputObject.PercentComplete = $percentComplete
		$outputObject.'Throughput(MB/sec)' = [math]::Round($kBytesWrittenPerSecondAverage/1024,1)
		$outputObject.EstimatedCompletion = "{0:g}" -f $completionTime
		$outputObject
		}
	}

10 thoughts on “Estimate the time to complete seeding a mailbox database copy

  1. Pingback: TOAA: Lokalisierte Server Software (oder auch: man lernt nie aus) | m-arx and the world.

  2. is working as expected …
    thanks a lot ….. also as Jamie – exactly what I was looking for

  3. Should this work for Exchange 2013 as well? I initiated a reseed of a complete server yesterday (29 DB’s, ca. 2 TB of data) and when I ran this script this morning it concluded “Could not calculate remaining time because throughput in the sampling interval was 0 kb”. Does that REALLY mean it just hasn’t been doing anything for the past 16 hours or so?

  4. Yes, it works with Exchange 2013 as the performance counters are the same. Throughput of 0 KB during the sampling period only means that no data was being written to the database during the time the script was looking at the performance counters. I can modify the script, however, to report the percentage completed even if it can’t tell when it will be completed.

Leave a Reply

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

*