diff --git a/docs/health-checks/README.md b/docs/health-checks/README.md index eda4049..1ec171a 100644 --- a/docs/health-checks/README.md +++ b/docs/health-checks/README.md @@ -48,6 +48,7 @@ A check only fires when its conditions are met, so an empty result for any check - **Tables Larger Than 50GB** - Identifies tables larger than 50GB (but less than 100GB) - **Query Duration Logging Disabled** - `log_min_duration_statement = -1` so slow queries never get logged - **Known Bug Affecting Your Version** - Notable non-CVE bugs from PostgreSQL release notes that match your running version (data integrity, replication, vacuum). Covers PG 15-18. +- **Unread Large Constraint-Backing Index** - Large unique or exclusion indexes (>100MB, 0 scans) that are still enforced on every write but never used for reads. The check fires on any `indisunique` or `indisexclusion` index, regardless of whether it backs a constraint. To clear the row: drop the index directly if it is standalone, or drop the underlying unique, primary-key, or exclusion constraint (PostgreSQL does not allow `DROP INDEX` on a constraint-backed index). ## LOW Priority Issues diff --git a/testing/pgTAP/04_medium_tests.sql b/testing/pgTAP/04_medium_tests.sql index dbb7333..7d51fff 100644 --- a/testing/pgTAP/04_medium_tests.sql +++ b/testing/pgTAP/04_medium_tests.sql @@ -2,7 +2,7 @@ BEGIN; -- Cache results once; querying inline per-assertion multiplies execution cost by N. CREATE TEMP TABLE _pgfa_func_results AS SELECT * FROM pg_firstAid(); CREATE TEMP TABLE _pgfa_view_results AS SELECT * FROM v_pgfirstaid; -SELECT plan(18); +SELECT plan(20); SELECT ok( (SELECT count(*) >= 0 FROM _pgfa_func_results WHERE check_name = 'Missing FK Index'), @@ -85,5 +85,14 @@ SELECT ok( 'View executes Query Duration Logging Disabled check' ); +SELECT ok( + (SELECT count(*) >= 0 FROM _pgfa_func_results WHERE check_name = 'Unread Large Constraint-Backing Index'), + 'Function executes Unread Large Constraint-Backing Index check' +); +SELECT ok( + (SELECT count(*) >= 0 FROM _pgfa_view_results WHERE check_name = 'Unread Large Constraint-Backing Index'), + 'View executes Unread Large Constraint-Backing Index check' +); + SELECT * FROM finish(); ROLLBACK; diff --git a/testing/seed_and_validate.py b/testing/seed_and_validate.py index eba4223..700423a 100644 --- a/testing/seed_and_validate.py +++ b/testing/seed_and_validate.py @@ -692,6 +692,8 @@ def start_session_threads( "Role Never Logged In", "Empty Table", "Index With Very Low Usage", + "Unread Large Constraint-Backing Index", + "Autovacuum Disabled On Table", } ) @@ -738,6 +740,15 @@ def start_session_threads( "Replication Slots Near Max Wal Size", "Table Bloat (Detailed)", "Idle Connections Over 1 Hour", + "Timestamp Without Time Zone", + "Varchar With Length Limit", + "Serial Column Legacy", + "Rules On Tables", + "Query Duration Logging Disabled", + "listen_addresses Wildcard", + "Known CVE Affecting Your Version", + "Known Bug Affecting Your Version", + "Not In With Subquery", } )