4. PROACTIVELY TUNING SQL SERVER PERFORMANCE WITH POWERSHELL
Now that you’ve seen some of the
building blocks of PowerShell it’s time to see how easy it is to
combine all this together and build some more functional scripts.
Remember, everything can be broken back down to cmdlets and variables;
so if you find that your script is getting too complex and difficult to
work with, break it back down and build it back up.
In this next section we will examine some scripts
that can be used to help with SQL Server tuning as we look at index
maintenance, managing disk space, and scripting out DDL data.
4.1 Index Maintenance
To ensure maximum performance is
obtained, index maintenance is an important job when managing a SQL
Server. Traditionally, a DBA may have written some T-SQL to perform
index maintenance, but this is not a simple task and one probably not
best suited to T-SQL because of the procedural nature of the task.
PowerShell offers an elegant solution to index maintenance in
collaboration with the SQL Server SMO library. The following script
shows how a fairly comprehensive index maintenance routine can be
performed in just a few lines of PowerShell. The script iterates
through all the indexes within all the tables of a user database, and
based on the fragmentation level of the index performs one of three
tasks (code file: PS_ManageFragmentation01.PS1):
- If the index is less than 5% fragmented, then do nothing because
the performance benefit of maintaining the index on this occurrence is
negligible.
- If the index is between 5% and 30% fragmented, then perform an index reorganization.
- If the index is greater than 30% fragmented, then perform an index rebuild.
[string] $ServerName = $args[0]
[string] $TargetDatabaseName = $args[1]
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-null
$server = New-Object Microsoft.SqlServer.Management.Smo.Server $ServerName
$targetDB = $server.Databases[$targetDatabaseName]
foreach ($table in $targetDB.Tables)
{
foreach($index in $table.Indexes)
{
$fragmentation = $index.EnumFragmentation()
$averageFragmentation = $fragmentation.Rows[0].AverageFragmentation
if($averageFragmentation -lt .05)
{
continue
}
if($averageFragmentation -ge .05 -and $averageFragmentation -lt .3)
{
$index.Reorganize()
continue
}
$index.Rebuild()
}
}
4.2 Managing Disk Space Utilization of Backups
Working with the file system is very
straightforward with PowerShell. In the following example, I have
created a small script that removes transaction log backups that are
older than two days, differential backups that are older than eight
days, and full backups that are older than 91 days. By splitting the Get-ChildItem
query into three queries based on file extension and last write time,
it was simply a matter of setting the number of days to subtract from
the current date to define the retention period for each backup type
(code file: PS_DeleteOldBackups01.PS1):
Get-ChildItem .\Backups -include *.trn -recurse '
| Where-Object { $_.lastwritetime -lt (Get-Date).AddDays(-2) } '
| Remove-Item
Get-ChildItem .\Backups -include *.dif -recurse '
| Where-Object { $_.lastwritetime -lt (Get-Date).AddDays(-8) } '
| Remove-Item
Get-ChildItem .\Backups -include *.bak -recurse '
| Where-Object { $_.lastwritetime -lt (Get-Date).AddDays(-91) } '
| Remove-Item