feat: add conditional VACUUM ANALYZE support to weekly monitoring scripts

This commit is contained in:
2026-07-07 08:31:33 -04:00
parent 4a408dc625
commit 81f8a702de
4 changed files with 367 additions and 5 deletions
+37 -3
View File
@@ -6,7 +6,8 @@
Sets up automated weekly performance monitoring via Windows Task Scheduler
.DESCRIPTION
Creates a scheduled task to run Weekly-Performance-Monitor.ps1 every Monday at 6 AM
Creates a scheduled task to run Weekly-Performance-Monitor.ps1 every Monday at 6 AM.
Can optionally enable conditional VACUUM ANALYZE based on dead tuple thresholds.
.PARAMETER Uninstall
Remove the scheduled task
@@ -17,12 +18,24 @@
.PARAMETER DayOfWeek
Day of week to run (default: Monday)
.PARAMETER EnableAutoVacuumAnalyze
Enable conditional VACUUM ANALYZE for tables above dead tuple thresholds
.PARAMETER DeadTupleThreshold
Minimum dead tuples before VACUUM ANALYZE runs (default: 10000)
.PARAMETER DeadTuplePercentThreshold
Minimum dead tuple percentage before VACUUM ANALYZE runs (default: 20)
.EXAMPLE
.\Setup-Weekly-Monitor.ps1
.EXAMPLE
.\Setup-Weekly-Monitor.ps1 -TaskTime "3am" -DayOfWeek Sunday
.EXAMPLE
.\Setup-Weekly-Monitor.ps1 -EnableAutoVacuumAnalyze -DeadTupleThreshold 10000 -DeadTuplePercentThreshold 20
.EXAMPLE
.\Setup-Weekly-Monitor.ps1 -Uninstall
#>
@@ -37,7 +50,18 @@ param (
[Parameter()]
[ValidateSet('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')]
[string]$DayOfWeek = 'Monday'
[string]$DayOfWeek = 'Monday',
[Parameter()]
[switch]$EnableAutoVacuumAnalyze,
[Parameter()]
[ValidateRange(1, [int]::MaxValue)]
[int]$DeadTupleThreshold = 10000,
[Parameter()]
[ValidateRange(0.01, 100.0)]
[double]$DeadTuplePercentThreshold = 20.0
)
$ErrorActionPreference = "Stop"
@@ -104,6 +128,11 @@ Write-ColorOutput "Configuration:" -Color Cyan
Write-ColorOutput " Task Name: $TaskName" -Color White
Write-ColorOutput " Script: $MonitorScript" -Color White
Write-ColorOutput " Schedule: Every $DayOfWeek at $TaskTime" -Color White
if ($EnableAutoVacuumAnalyze) {
Write-ColorOutput " Auto VACUUM ANALYZE: Enabled (dead tuples >= $DeadTupleThreshold, dead percent >= $DeadTuplePercentThreshold)" -Color White
} else {
Write-ColorOutput " Auto VACUUM ANALYZE: Disabled" -Color White
}
Write-ColorOutput ""
# Remove existing task if present
@@ -116,9 +145,14 @@ if ($existingTask) {
# Create scheduled task action
Write-ColorOutput "Creating scheduled task..." -Color Cyan
$scriptArguments = "-NoProfile -ExecutionPolicy Bypass -File `"$MonitorScript`""
if ($EnableAutoVacuumAnalyze) {
$scriptArguments += " -AutoVacuumAnalyze -DeadTupleThreshold $DeadTupleThreshold -DeadTuplePercentThreshold $DeadTuplePercentThreshold"
}
$action = New-ScheduledTaskAction `
-Execute "PowerShell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -File `"$MonitorScript`""
-Argument $scriptArguments
# Create trigger
$trigger = New-ScheduledTaskTrigger `
+89 -2
View File
@@ -10,7 +10,8 @@
2. Analyzes slow queries
3. Tracks index usage over time
4. Generates weekly performance reports
5. Can be scheduled via Task Scheduler
5. Optionally runs VACUUM ANALYZE on tables with high dead tuples
6. Can be scheduled via Task Scheduler
.PARAMETER OutputDirectory
Directory to save reports (default: reports/weekly)
@@ -27,6 +28,9 @@
.EXAMPLE
.\Weekly-Performance-Monitor.ps1 -OutputDirectory "C:\Reports\Jellyfin" -CompareWithPrevious
.EXAMPLE
.\Weekly-Performance-Monitor.ps1 -AutoVacuumAnalyze -DeadTupleThreshold 10000 -DeadTuplePercentThreshold 20
.EXAMPLE
# Schedule weekly via Task Scheduler
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Path\To\Weekly-Performance-Monitor.ps1"
@@ -47,7 +51,18 @@ param (
[switch]$EmailReport,
[Parameter()]
[switch]$CompareWithPrevious
[switch]$CompareWithPrevious,
[Parameter()]
[switch]$AutoVacuumAnalyze,
[Parameter()]
[ValidateRange(1, [int]::MaxValue)]
[int]$DeadTupleThreshold = 10000,
[Parameter()]
[ValidateRange(0.01, 100.0)]
[double]$DeadTuplePercentThreshold = 20.0
)
# ============================================================================
@@ -217,6 +232,67 @@ ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
}
}
function Invoke-ConditionalVacuumAnalyze {
param(
[int]$MinDeadTuples,
[double]$MinDeadPercent
)
Write-ColorOutput "`nChecking for tables that need VACUUM ANALYZE..." -Color Cyan
Write-ColorOutput "Thresholds: dead tuples >= $MinDeadTuples and dead percent >= $MinDeadPercent" -Color Gray
$tableQuery = @"
SELECT
format('%I.%I', schemaname, tablename) AS qualified_table,
n_dead_tup,
ROUND(100.0 * n_dead_tup / NULLIF(n_live_tup, 0), 2) AS dead_pct
FROM pg_stat_user_tables
WHERE schemaname IN ('library', 'users', 'authentication', 'displaypreferences', 'activitylog')
AND n_live_tup > 0
AND n_dead_tup >= $MinDeadTuples
AND (100.0 * n_dead_tup / NULLIF(n_live_tup, 0)) >= $MinDeadPercent
ORDER BY n_dead_tup DESC;
"@
try {
$tables = & $PSQL_PATH -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -t -A -F "|" -c $tableQuery 2>&1
if ($LASTEXITCODE -ne 0) {
Write-ColorOutput "[ERROR] Failed to evaluate dead tuple thresholds: $tables" -Color Red
return $false
}
$tableLines = @($tables | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
if ($tableLines.Count -eq 0) {
Write-ColorOutput "[OK] No tables exceeded dead tuple thresholds" -Color Green
return $true
}
Write-ColorOutput "Found $($tableLines.Count) table(s) requiring VACUUM ANALYZE" -Color Yellow
foreach ($line in $tableLines) {
$parts = $line -split "\|", 3
$qualifiedTable = $parts[0].Trim()
$deadTuples = if ($parts.Count -ge 2) { $parts[1].Trim() } else { "unknown" }
$deadPercent = if ($parts.Count -ge 3) { $parts[2].Trim() } else { "unknown" }
Write-ColorOutput "Running VACUUM ANALYZE on $qualifiedTable (dead tuples: $deadTuples, dead percent: $deadPercent)" -Color Cyan
$vacuumResult = & $PSQL_PATH -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -c "VACUUM (ANALYZE, VERBOSE) $qualifiedTable;" 2>&1
if ($LASTEXITCODE -ne 0) {
Write-ColorOutput "[ERROR] VACUUM ANALYZE failed for $qualifiedTable: $vacuumResult" -Color Red
return $false
}
Write-ColorOutput "[OK] VACUUM ANALYZE completed for $qualifiedTable" -Color Green
}
return $true
} catch {
Write-ColorOutput "[ERROR] Conditional VACUUM ANALYZE failed: $_" -Color Red
return $false
}
}
function Compare-WithPrevious {
param(
[string]$CurrentReport,
@@ -361,6 +437,17 @@ Get-IndexUsageStats -OutputFile $indexUsageFile | Out-Null
$tableSizesFile = Join-Path $reportDir "table_sizes_$timestamp.txt"
Get-TableSizeStats -OutputFile $tableSizesFile | Out-Null
# Optionally vacuum/analyze tables that exceed dead tuple thresholds
if ($AutoVacuumAnalyze) {
$vacuumSuccess = Invoke-ConditionalVacuumAnalyze `
-MinDeadTuples $DeadTupleThreshold `
-MinDeadPercent $DeadTuplePercentThreshold
if (-not $vacuumSuccess) {
Write-ColorOutput "[WARN] Conditional VACUUM ANALYZE encountered errors" -Color Yellow
}
}
# Compare with previous week if requested
if ($CompareWithPrevious) {
Compare-WithPrevious -CurrentReport $diagnosticsFile -OutputDirectory $reportDir