cockroachdb / cockroachdb/cockroach
sql: automatically validate index drops before removing unused indexes
- Dominant language
- Go
- Stars
- 32.5k
- Forks
- 4.1k
- PR merge metrics
- PR metrics pending
Description
**Is your feature request related to a problem? Please describe.**
CockroachDB already has observability that identifies indexes as unused
based on recent read traffic. Acting on that signal — actually dropping
the index — still carries risk: a query that runs rarely (a nightly
report, a quarterly job, a future workload shift) may rely on the index
even when recent traffic shows no use. Dropping an index that turns out
to still be load-bearing causes a sudden plan regression with no easy
rollback (recreating the index can be slow and may not produce the same
plan immediately).
Today the operator bears all of this risk, and there is no built-in
mechanism to validate that a drop is safe before it is committed.
**Describe the solution you'd like**
A feature that takes existing unused-index signals as input and
validates the drop against the live workload before actually removing
the index, using index visibility as the experimentation primitive:
1. The system marks the candidate index as fully invisible (or
partially invisible, e.g. visible to ~5% of queries as a control).
2. The optimizer plans without the index for the invisible fraction,
exactly as it would after a drop, while the index itself remains
on disk and continues to be maintained.
3. For each statement whose plan changes when the index becomes
invisible, we measure the resulting performance and compare against
the prior baseline (statement statistics, plan fingerprints).
4. After a trial period (configurable by time and/or sample count),
the system decides:
- If no statement regresses meaningfully, promote the change to a
real `DROP INDEX`.
- If regressions appear, abort the drop and make the index fully
visible again. Surface which statement fingerprints regressed so
the operator understands why.
The decision policy should be conservative — defaulting to *not*
dropping when the signal is ambiguous — and should expose its reasoning
via `crdb_internal` so operators can inspect and override.
**Describe alternatives you've considered**
An alternative experimentation primitive: keep the index visible but,
for a sampled fraction of statements, run the query twice — once with
the index forced out of consideration, and once normally — and compare.
This avoids any production traffic actually being served by a plan that
ignores the index until it's been validated, at the cost of extra work
per sampled query and added complexity in the execution path. The
invisibility approach is simpler and reuses existing machinery.
Other alternatives:
- Manual operator-driven validation (status quo): mark invisible by
hand, watch for regressions, drop later. Works but is tedious and
rarely done in practice.
- Long observation windows on the unused-index signal alone — does not
catch workloads that change suddenly or rely on rare queries.
**Additional context**
This is the symmetric counterpart to validating *new* index
recommendations (filed separately). Both rely on the same underlying
experimentation primitives (partial visibility / invisible indexes,
sampled dual-plan execution) and the same per-statement attribution of
performance changes.
Detection of which indexes are unused is handled by existing
observability and is not part of this feature — this issue only covers
the validation step between "we think this index is unused" and the
actual `DROP INDEX`.
Open design questions:
- How long should the trial period be, and how is "no meaningful
regression" defined?
- How do we handle indexes that are unused for reads but enforce
uniqueness or back foreign keys? (Should be excluded up front.)
- Interaction with schema changes, backups, and rolling upgrades.
- Should the workflow be opt-in per index, per table, or cluster-wide?
Epic CRDB-64888
Jira issue: CRDB-64890
Contributor guide
Research direction
Start by studying the existing index-visibility machinery, unused-index observability, statement statistics, and plan fingerprints described in the issue. Define the trial workflow, conservative regression policy, exclusions, configuration, and crdb_internal inspection surface before implementation. Done means a candidate index can be validated against live workload, safely restored on regression, or promoted to DROP INDEX with the decision and affected statement fingerprints exposed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100