bin/Public/Get-sqmIndexFragmentation.ps1
|
<# .SYNOPSIS Analysiert die Fragmentierung von Indizes in einer oder mehreren Datenbanken. .DESCRIPTION Liefert fuer alle Indizes den Fragmentierungsgrad (%) und empfiehlt Aktion: - 5-30% ? REORGANIZE - >30% ? REBUILD Die Ausgabe kann auf bestimmte Datenbanken, Tabellen oder einen Mindestfragmentierungsgrad beschraenkt werden. .PARAMETER SqlInstance SQL Server-Instanz (Standard: aktueller Computername). .PARAMETER SqlCredential PSCredential fuer die Verbindung. .PARAMETER Database Datenbankname oder Wildcard-Muster (z.B. 'Sales*'). Standard: alle Benutzerdatenbanken. .PARAMETER TableName Tabellenname oder Wildcard-Muster (z.B. 'Order*'). Standard: alle Tabellen. .PARAMETER MinFragmentationPercent Nur Indizes mit Fragmentierung >= diesem Wert anzeigen. Standard: 5. .PARAMETER PageCountMin Nur Indizes mit mindestens dieser Seitenzahl anzeigen. Standard: 0 (alle Indizes). .PARAMETER OutputPath Optionaler CSV-Exportpfad. .PARAMETER EnableException Ausnahmen sofort ausloesen. .EXAMPLE Get-sqmIndexFragmentation -Database 'AdventureWorks' -MinFragmentationPercent 10 .EXAMPLE Get-sqmIndexFragmentation -SqlInstance 'SQL01' -MinFragmentationPercent 30 .NOTES Verwendet sys.dm_db_index_physical_stats (LIMITED-Modus) via Invoke-DbaQuery. Erfordert dbatools und VIEW DATABASE STATE auf den Zieldatenbanken. #> function Get-sqmIndexFragmentation { [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $false)] [string]$SqlInstance = $env:COMPUTERNAME, [Parameter(Mandatory = $false)] [System.Management.Automation.PSCredential]$SqlCredential, [Parameter(Mandatory = $false)] [string]$Database = '*', [Parameter(Mandatory = $false)] [string]$TableName = '*', [Parameter(Mandatory = $false)] [int]$MinFragmentationPercent = 5, [Parameter(Mandatory = $false)] [int]$PageCountMin = 0, [Parameter(Mandatory = $false)] [string]$OutputPath, [Parameter(Mandatory = $false)] [switch]$EnableException ) begin { $functionName = $MyInvocation.MyCommand.Name if (-not $script:dbatoolsAvailable) { $errMsg = "dbatools-Modul nicht gefunden. Bitte installieren: Install-Module dbatools" Invoke-sqmLogging -Message $errMsg -FunctionName $functionName -Level "ERROR" throw $errMsg } $results = [System.Collections.Generic.List[PSCustomObject]]::new() } process { try { # Get-DbaDatabase unterstuetzt keine Wildcards im -Database-Parameter. # Daher: alle Benutzerdatenbanken laden und anschliessend per -like filtern. $allDbs = Get-DbaDatabase -SqlInstance $SqlInstance -SqlCredential $SqlCredential ` -ExcludeSystem -ErrorAction Stop $dbList = if ($Database -eq '*') { $allDbs } else { $allDbs | Where-Object { $_.Name -like $Database } } if (-not $dbList) { Invoke-sqmLogging -Message "Keine Datenbanken auf '$SqlInstance' gefunden (Filter: '$Database')." ` -FunctionName $functionName -Level "WARNING" return $results } # Fragmentierungsdaten kommen aus sys.dm_db_index_physical_stats (DMV), # nicht aus SMO-Index-Objekten (Get-DbaDbIndex liefert keine FragPercent/PageCount). $query = @" SELECT OBJECT_SCHEMA_NAME(ips.object_id) AS SchemaName, OBJECT_NAME(ips.object_id) AS TableName, i.name AS IndexName, i.type_desc AS IndexType, ips.avg_fragmentation_in_percent AS AvgFragmentationPercent, ips.page_count AS PageCount FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips INNER JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id WHERE ips.index_id > 0 AND ips.page_count >= $PageCountMin AND ips.avg_fragmentation_in_percent >= $MinFragmentationPercent ORDER BY ips.avg_fragmentation_in_percent DESC "@ foreach ($db in $dbList) { try { $rows = Invoke-DbaQuery -SqlInstance $SqlInstance -SqlCredential $SqlCredential ` -Database $db.Name -Query $query -ErrorAction Stop foreach ($row in $rows) { # Tabellen-Wildcard-Filter (in PowerShell, da Parametername kein SQL-Parameter ist) if ($TableName -ne '*' -and $row.TableName -notlike $TableName) { continue } $frag = $row.AvgFragmentationPercent $action = if ($frag -lt 30) { 'REORGANIZE' } else { 'REBUILD' } $results.Add([PSCustomObject]@{ SqlInstance = $SqlInstance Database = $db.Name Schema = $row.SchemaName TableName = $row.TableName IndexName = $row.IndexName IndexType = $row.IndexType PageCount = $row.PageCount FragPercent = [math]::Round($frag, 2) RecommendedAction = $action }) } } catch { Invoke-sqmLogging -Message "Fehler in DB '$($db.Name)': $($_.Exception.Message)" ` -FunctionName $functionName -Level "WARNING" if ($EnableException) { throw } } } if ($OutputPath) { $results | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 -Force Invoke-sqmLogging -Message "CSV exportiert nach $OutputPath" -FunctionName $functionName -Level "INFO" } return $results } catch { Invoke-sqmLogging -Message $_.Exception.Message -FunctionName $functionName -Level "ERROR" if ($EnableException) { throw } return $null } } } |