I’ve put together the below PowerShell script this week to identify collections in ConfigMgr that require the longest time to refresh. If you ever experience a decrease in ConfigMgr collection update performance, you might want to run this script to find potential collections that have a long refresh duration.
Function Get-CMCollectionRefreshDuration
{
<#
.Synopsis
Get-CMCollectionRefreshDuration displays the duration of Configuration Manager refresh cycles
.DESCRIPTION
Inefficient queries can cause long collection refresh cycles. Use the Get-CMCollectionRefreshDuration
cmdlet to identify collections with long refresh cycles.
.EXAMPLE
Get-CMCollectionRefreshDuration -DataSource sqlsrv01\instance1 -Database CM_DB1
Collection EvaluationStartTime LastRefreshTime Duration
---------- ------------------- --------------- --------
Collection1 30.08.2014 09:20:11 30.08.2014 09:22:45 00:02:33
Collection2 30.08.2014 09:27:31 30.08.2014 09:30:05 00:02:33
Collection3 30.08.2014 07:01:23 30.08.2014 07:03:56 00:02:33
Collection4 30.08.2014 07:20:38 30.08.2014 07:23:11 00:02:33
Collection5 30.08.2014 07:05:00 30.08.2014 07:07:33 00:02:33
.EXAMPLE
Get-CMCollectionRefreshDuration -DataSource sqlsrv01\instance1 -Database CM_DB1 -ShowTopCollections 100
Lists the top 100 collections
.PARAMETER DataSource
The name of the SQL Server that hosts the configuration manager database
<servername\instance>
.PARAMETER Database
The database name of the configuration manager database
.PARAMETER ShowTopCollections
The number of collections to show that have the longers collection refresh cycle duration
#>
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$false,
Position=0,
HelpMessage="Enter the SQL Server datasource name <server\instance>")]
[string]$DataSource="server01\instance1",
[Parameter(Mandatory=$false,
Position=1,
HelpMessage="The database name of the ConfigMgr database")]
[string]$Database="CMDB1",
[Parameter(Mandatory=$false,
Position=2,
HelpMessage="The number of top collectons to show")]
[ValidateRange(1,10000)]
[int]$ShowTopCollections="5"
)
Begin{
# connecting to SQL server
Try{
$Connection = New-Object System.Data.SqlClient.SqlConnection
$Connection.ConnectionString = "Data Source=$DataSource;Integrated Security=True"
$Connection.Open()
}
Catch [Exception]
{
write-output "Unable to connect to $DataSource"
Write-Output $_.Exception
Throw
}
$query = "
SELECT TOP $ShowTopCollections
[CollectionName],
[EvaluationStartTime],
[LastRefreshTime],
CAST([LastRefreshTime] - [EvaluationStartTime] as datetime) as Duration
FROM [$Database].[dbo].[Collections]
ORDER BY CAST([LastRefreshTime] - [EvaluationStartTime] as datetime) DESC"
$command = $connection.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$table = new-object “System.Data.DataTable”
$table.Load($result)
$Connection.Close()
}
Process{
$colupdateduration = @()
ForEach($cud in $table)
{
$object = New-Object -TypeName PSObject
$object | Add-Member -MemberType NoteProperty -Name "Collection" -Value $cud.Collectionname
$object | Add-Member -MemberType NoteProperty -Name "EvaluationStartTime" -Value $cud.EvaluationStartTime
$object | Add-Member -MemberType NoteProperty -Name "LastRefreshTime" -Value $cud.LastRefreshTime
$object | Add-Member -MemberType NoteProperty -Name "Duration" -Value ($dur = Get-date $cud.Duration -Format "HH:mm:ss")
$colupdateduration += $object
}
}
End{
$colupdateduration
}
}
Thanks to Roger Zander and Claude Henchoz for the SQL query to find these collections.