Skip to content

sp_IndexCleanup: performance + bug fix #721#723

Merged
erikdarlingdata merged 6 commits intomainfrom
dev
Mar 25, 2026
Merged

sp_IndexCleanup: performance + bug fix #721#723
erikdarlingdata merged 6 commits intomainfrom
dev

Conversation

@erikdarlingdata
Copy link
Copy Markdown
Owner

Summary

Performance: Stage dm_db_index_usage_stats into temp table with clustered PK, scoped to #filtered_objects. Eliminates 52M-row nested loop DMV scan (~4 minutes → seconds).

Schema join: Replace LEFT JOIN sys.tables + sys.views + ISNULL(t.schema_id, v.schema_id) with JOIN sys.objects in all 4 queries. Eliminates non-SARGable late filter.

Bug fix (#721): Unique constraints now recognized as superset targets in Key Subset detection. NC indexes that are a prefix of a UC's keys are correctly flagged for DISABLE.

Closes #721

🤖 Generated with Claude Code

erikdarlingdata and others added 6 commits March 24, 2026 22:32
…scans

The LEFT JOIN to dm_db_index_usage_stats was executed via nested loops,
scanning the full DMV per row (52M actual rows, ~4 minutes). Now
pre-stages the DMV for the current database into #usage_stats with a
clustered PK on (object_id, index_id) before the main query, then
LEFT JOINs to the temp table instead.

Handles the database cursor loop with TRUNCATE on re-entry.

Tested on SQL2022 (StackOverflow2013) and SQL2016 (StackOverflow2010).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…sage-stats

sp_IndexCleanup: stage dm_db_index_usage_stats to fix 4-minute scan
Adds EXISTS filter against #filtered_objects when populating
#usage_stats, so only indexes on objects we're analyzing are staged
instead of every touched index in the database.

Tested on SQL2022.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…sage-stats

sp_IndexCleanup: scope usage stats staging to filtered objects
…ULL schema join

Issue #721: Unique constraints were excluded from both sides of the
Key Subset rule, so a NC index that was a prefix of a UC's keys was
never flagged. Removed the NOT EXISTS check on the wider (target) side
so UCs can serve as the superset target. The narrower-side check stays
to prevent disabling UCs themselves.

Schema join: Replaced LEFT JOIN sys.tables + LEFT JOIN sys.views +
ISNULL(t.schema_id, v.schema_id) with a single JOIN sys.objects in
all 4 query locations. Eliminates the non-SARGable ISNULL predicate
that caused late filtering in the optimizer.

Also scoped #usage_stats staging to #filtered_objects.

Tested on SQL2022 (repro from #721 confirmed fixed) and SQL2016.

Closes #721

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…et-and-schema-join

sp_IndexCleanup: fix #721 unique constraint subset + replace ISNULL schema join
@erikdarlingdata erikdarlingdata merged commit 6e6673e into main Mar 25, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Will not merge unique constraint with a non clustered index when keys are duplicated

1 participant