feat: add conditional VACUUM ANALYZE support with thresholds to performance monitor script
This commit is contained in:
@@ -51,7 +51,18 @@ param (
|
|||||||
[switch]$EmailReport,
|
[switch]$EmailReport,
|
||||||
|
|
||||||
[Parameter()]
|
[Parameter()]
|
||||||
[switch]$CompareWithPrevious
|
[switch]$CompareWithPrevious,
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[switch]$AutoVacuumAnalyze,
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[ValidateRange(1, [int]::MaxValue)]
|
||||||
|
[int]$DeadTupleThreshold = 100,
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[ValidateRange(0.01, 100.0)]
|
||||||
|
[double]$DeadTuplePercentThreshold = 0.02
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -158,15 +169,15 @@ function Get-IndexUsageStats {
|
|||||||
$query = @"
|
$query = @"
|
||||||
SELECT
|
SELECT
|
||||||
schemaname,
|
schemaname,
|
||||||
tablename,
|
relname AS tablename,
|
||||||
indexname,
|
indexrelname,
|
||||||
idx_scan,
|
idx_scan,
|
||||||
idx_tup_read,
|
idx_tup_read,
|
||||||
idx_tup_fetch,
|
idx_tup_fetch,
|
||||||
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
|
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
|
||||||
FROM pg_stat_user_indexes
|
FROM pg_stat_user_indexes
|
||||||
WHERE schemaname IN ('library', 'users', 'authentication', 'displaypreferences', 'activitylog')
|
WHERE schemaname IN ('library', 'users', 'authentication', 'displaypreferences', 'activitylog')
|
||||||
ORDER BY schemaname, tablename, idx_scan DESC;
|
ORDER BY schemaname, relname, idx_scan DESC;
|
||||||
"@
|
"@
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -193,7 +204,7 @@ function Get-TableSizeStats {
|
|||||||
$query = @"
|
$query = @"
|
||||||
SELECT
|
SELECT
|
||||||
schemaname,
|
schemaname,
|
||||||
relname AS tablename,
|
relname,
|
||||||
pg_size_pretty(pg_total_relation_size(schemaname||'.'||relname)) AS total_size,
|
pg_size_pretty(pg_total_relation_size(schemaname||'.'||relname)) AS total_size,
|
||||||
pg_size_pretty(pg_relation_size(schemaname||'.'||relname)) AS table_size,
|
pg_size_pretty(pg_relation_size(schemaname||'.'||relname)) AS table_size,
|
||||||
pg_size_pretty(pg_total_relation_size(schemaname||'.'||relname) - pg_relation_size(schemaname||'.'||relname)) AS index_size,
|
pg_size_pretty(pg_total_relation_size(schemaname||'.'||relname) - pg_relation_size(schemaname||'.'||relname)) AS index_size,
|
||||||
@@ -221,6 +232,67 @@ ORDER BY pg_total_relation_size(schemaname||'.'||relname) 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, relname) 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 {
|
function Compare-WithPrevious {
|
||||||
param(
|
param(
|
||||||
[string]$CurrentReport,
|
[string]$CurrentReport,
|
||||||
|
|||||||
Reference in New Issue
Block a user