Skip to content

Commit

Permalink
Set-DbaDbCompression, prefer online rebuilds where possible (#9118)
Browse files Browse the repository at this point in the history
  • Loading branch information
niphlod authored Oct 10, 2023
1 parent 44fd060 commit 0bfa72b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 8 deletions.
54 changes: 47 additions & 7 deletions public/Set-DbaDbCompression.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ function Set-DbaDbCompression {
.PARAMETER PercentCompression
Will only work on the tables/indexes that have the calculated savings at and higher for the given number provided.
.PARAMETER ForceOfflineRebuilds
By default, this function prefers online rebuilds over offline ones.
If you are on a supported version of SQL Server but still prefer to do offline rebuilds, enable this flag
.PARAMETER InputObject
Takes the output of Test-DbaDbCompression as an object and applied compression based on those recommendations.
Expand Down Expand Up @@ -114,10 +118,12 @@ function Set-DbaDbCompression {
[string]$CompressionType = "Recommended",
[int]$MaxRunTime = 0,
[int]$PercentCompression = 0,
[switch]$ForceOfflineRebuilds,
$InputObject,
[switch]$EnableException
)


process {
$starttime = Get-Date
foreach ($instance in $SqlInstance) {
Expand All @@ -131,15 +137,13 @@ function Set-DbaDbCompression {
if ($server.EngineEdition -notmatch 'Enterprise' -and $server.VersionMajor -lt '13') {
Stop-Function -Message "Only SQL Server Enterprise Edition supports compression on $server" -Target $server -Continue
}

$dbs = $server.Databases | Where-Object { $_.IsAccessible -and $_.IsSystemObject -eq 0 }
if ($Database) {
$dbs = $dbs | Where-Object { $_.Name -in $Database }
}
if ($ExcludeDatabase) {
$dbs = $dbs | Where-Object { $_.Name -NotIn $ExcludeDatabase }
}

foreach ($db in $dbs) {
Write-Message -Level Verbose -Message "Querying $instance - $db"
if ($db.Status -ne 'Normal') {
Expand All @@ -150,6 +154,28 @@ function Set-DbaDbCompression {
Write-Message -Level Warning -Message "$db has a compatibility level lower than Version100 and will be skipped."
continue
}
$isOnlineRebuildSupported = $false
# Loop on indexes to see if Rebuild Online is supported
$onlineRebuildScanCompleted = $false
foreach ($obj in $tables | Where-Object { !$_.IsMemoryOptimized -and !$_.HasSparseColumn }) {
if ($onlineRebuildScanCompleted) {
break
}
foreach ($index in $($obj.Indexes | Where-Object { !$_.IsMemoryOptimized -and $_.IndexType -notmatch 'Columnstore' })) {
if ($index.IsOnlineRebuildSupported -or $server.isAzure) {
$isOnlineRebuildSupported = $true
$onlineRebuildScanCompleted = $true
break
}
}
}
Write-Message -Level Verbose -Message "Are Online Rebuilds supported ? $isOnlineRebuildSupported"
$CanDoOnlineOperation = $false
if ($IsOnlineRebuildSupported -and !$ForceOfflineRebuilds) {
$CanDoOnlineOperation = $true
Write-Message -Level Verbose -Message "Using Online Rebuilds where possible"
}

if ($CompressionType -eq "Recommended") {
if (Test-Bound "InputObject") {
Write-Message -Level Verbose -Message "Using passed in compression suggestions"
Expand All @@ -176,6 +202,7 @@ function Set-DbaDbCompression {
Write-Message -Level Verbose -Message "Applying $($obj.CompressionTypeRecommendation) compression to $($obj.Database).$($obj.Schema).$($obj.TableName)"
try {
($server.Databases[$obj.Database].Tables[$obj.TableName, $obj.Schema].PhysicalPartitions | Where-Object { $_.PartitionNumber -eq $obj.Partition }).DataCompression = $obj.CompressionTypeRecommendation
$server.Databases[$obj.Database].Tables[$obj.TableName, $obj.Schema].OnlineHeapOperation = $CanDoOnlineOperation
$server.Databases[$obj.Database].Tables[$obj.TableName, $obj.Schema].Rebuild()
} catch {
Stop-Function -Message "Compression failed for $instance - $db - table $($obj.Schema).$($obj.TableName) - partition $($obj.Partition)" -Target $db -ErrorRecord $_ -Continue
Expand All @@ -184,8 +211,10 @@ function Set-DbaDbCompression {
##nonclustered indexes
Write-Message -Level Verbose -Message "Applying $($obj.CompressionTypeRecommendation) compression to $($obj.Database).$($obj.Schema).$($obj.TableName).$($obj.IndexName)"
try {
($server.Databases[$obj.Database].Tables[$obj.TableName, $obj.Schema].Indexes[$obj.IndexName].PhysicalPartitions | Where-Object { $_.PartitionNumber -eq $obj.Partition }).DataCompression = $obj.CompressionTypeRecommendation
$server.Databases[$obj.Database].Tables[$obj.TableName, $obj.Schema].Indexes[$obj.IndexName].Rebuild()
$underlyingObj = $server.Databases[$obj.Database].Tables[$obj.TableName, $obj.Schema].Indexes[$obj.IndexName]
($underlyingObj.PhysicalPartitions | Where-Object { $_.PartitionNumber -eq $obj.Partition }).DataCompression = $obj.CompressionTypeRecommendation
$underlyingObj.OnlineIndexOperation = $CanDoOnlineOperation
$underlyingObj.Rebuild()
} catch {
Stop-Function -Message "Compression failed for $instance - $db - table $($obj.Schema).$($obj.TableName) - index $($obj.IndexName) - partition $($obj.Partition)" -Target $db -ErrorRecord $_ -Continue
}
Expand All @@ -210,6 +239,7 @@ function Set-DbaDbCompression {
Write-Message -Level Verbose -Message "Compressing table $($obj.Schema).$($obj.Name)"
try {
$($obj.PhysicalPartitions | Where-Object { $_.PartitionNumber -eq $p.PartitionNumber }).DataCompression = $CompressionType
$obj.OnlineHeapOperation = $CanDoOnlineOperation
$obj.Rebuild()
} catch {
Stop-Function -Message "Compression failed for $instance - $db - table $($obj.Schema).$($obj.Name) - partition $($p.PartitionNumber)" -Target $db -ErrorRecord $_ -Continue
Expand Down Expand Up @@ -249,10 +279,16 @@ function Set-DbaDbCompression {
## Once this UserVoice item is fixed the workaround can be removed
## https://feedback.azure.com/forums/908035-sql-server/suggestions/34080112-data-compression-smo-bug
if ($CompressionType -eq "None") {
$query = "ALTER INDEX [$($index.Name)] ON $($index.Parent) REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = $CompressionType)"
$query = "ALTER INDEX [$($index.Name)] ON $($index.Parent) REBUILD PARTITION = ALL WITH"
if ($CanDoOnlineOperation) {
$query += "(DATA_COMPRESSION = $CompressionType, ONLINE = ON)"
} else {
$query += "(DATA_COMPRESSION = $CompressionType)"
}
$Server.Query($query, $db.Name)
} else {
$($index.PhysicalPartitions | Where-Object { $_.PartitionNumber -eq $P.PartitionNumber }).DataCompression = $CompressionType
$index.OnlineIndexOperation = $CanDoOnlineOperation
$index.Rebuild()
}
} catch {
Expand Down Expand Up @@ -290,11 +326,15 @@ function Set-DbaDbCompression {
## Once this UserVoice item is fixed the workaround can be removed
## https://feedback.azure.com/forums/908035-sql-server/suggestions/34080112-data-compression-smo-bug
if ($CompressionType -eq "None") {
$query = "ALTER INDEX [$($index.Name)] ON $($index.Parent) REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = $CompressionType)"
$query
if ($CanDoOnlineOperation) {
$query += "(DATA_COMPRESSION = $CompressionType, ONLINE = ON)"
} else {
$query += "(DATA_COMPRESSION = $CompressionType)"
}
$Server.Query($query, $db.Name)
} else {
$($index.PhysicalPartitions | Where-Object { $_.PartitionNumber -eq $P.PartitionNumber }).DataCompression = $CompressionType
$index.OnlineIndexOperation = $CanDoOnlineOperation
$index.Rebuild()
}
} catch {
Expand Down
2 changes: 1 addition & 1 deletion tests/Set-DbaDbCompression.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Write-Host -Object "Running $PSCommandpath" -ForegroundColor Cyan
Describe "$CommandName Unit Tests" -Tag 'UnitTests' {
Context "Validate parameters" {
[object[]]$params = (Get-Command $CommandName).Parameters.Keys | Where-Object {$_ -notin ('whatif', 'confirm')}
[object[]]$knownParameters = 'SqlInstance', 'SqlCredential', 'Database', 'ExcludeDatabase', 'Table', 'CompressionType', 'MaxRunTime', 'PercentCompression', 'InputObject', 'EnableException'
[object[]]$knownParameters = 'SqlInstance', 'SqlCredential', 'Database', 'ExcludeDatabase', 'Table', 'CompressionType', 'MaxRunTime', 'PercentCompression', 'ForceOfflineRebuilds', 'InputObject', 'EnableException'
$knownParameters += [System.Management.Automation.PSCmdlet]::CommonParameters
It "Should only contain our specific parameters" {
(@(Compare-Object -ReferenceObject ($knownParameters | Where-Object {$_}) -DifferenceObject $params).Count ) | Should Be 0
Expand Down

0 comments on commit 0bfa72b

Please sign in to comment.