Skip to content

CONCEPT Cited by 1 source

Index-usage time series

An index-usage time series is a per-query-pattern record, over time, of which indexes the database used to execute the pattern. The axes:

  • X — time (binned, e.g. 15-second, 1-minute, 1-hour intervals).
  • Y — percentage (or count) of pattern executions that used each named index in that bin.
  • One line per index, plus (often) a zero-index line for unindexed executions.

Canonicalised by PlanetScale as the Indexes tab in Insights. (Source: sources/2026-04-21-planetscale-tracking-index-usage-with-insights.)

Distinct from neighbouring primitives

Primitive What it shows When it's right
EXPLAIN output Planner-predicted index for one query, one moment Pre-deployment verification; hypothetical index testing
table_io_waits_summary_by_index_usage Global per-(table, index) row-read counters since restart Per-table "who's using this index?" roll-up
Index-usage time series Per-pattern, over-time, percentage of executions per index Diagnosing optimiser flaps, cumulative usage graphs, "is my new index actually getting used?"

The time-series surface is the only one that captures optimiser flapping — when the planner alternates between two candidate indexes as statistics drift. EXPLAIN shows the current plan; performance_schema shows cumulative since-restart counters; the time-series shows the transition.

Diagnostic reads

  • One flat line at 100% — optimiser consistently uses the same index. Healthy.
  • Two or more lines summing to 100% — optimiser is flipping between candidates. Often benign; sometimes reveals a missing covering index.
  • Line stepping down to 0% — something stopped using the index. Schema change, table statistics update, workload shift. Pair with deploy-marker overlay (concepts/deploy-marker-annotation) to attribute.
  • Unindexed line > 0% — full-table scan; candidate for new index. Pair with indexed:false query_count:>X p50:>Y search predicate to find unindexed high-volume slow patterns.
  • Unindexed line = 100% — there is no usable index for this pattern.

Visualisation components

From the post:

  • Main graph — time-series of index-usage percentages per pattern, one line per index.
  • Bottom bar graph — cumulative usage over the selected time span (bar per index, same colour encoding).

The bottom bar is the time-aggregated complement to the line graph — answers "across this whole time range, what was the overall mix?"

Multi-predicate search composition

The time-series surface composes with Insights' search predicate language:

  • index:products.idx_price — all patterns using the products.idx_price index. Inverse direction (per-index view; see patterns/bidirectional-index-query-attribution).
  • indexed:false — unindexed patterns.
  • indexed:false query_count:>1000 p50:>250 — unindexed patterns run > 1000 times in the last 24 hours with p50 > 250 ms. This multi-predicate filter is the productised form of the "sort digests by rows_examined and filter for type: ALL" diagnostic workflow canonicalised by patterns/digest-based-query-prioritization.

Substrate

Built on top of:

Aggregation cadence: 15-second flush from VTGate into the Insights pipeline, matching all other per-pattern aggregate axes.

Caveats

  • SELECT-only — see concepts/select-only-index-telemetry-caveat. DML index usage is not shown.
  • InnoDB-only — other storage engines not reported (not that PlanetScale supports them).
  • Percentage + cumulative bar, no rows-per-index — for per-index row counts, still need performance_schema.

Seen in

  • sources/2026-04-21-planetscale-tracking-index-usage-with-insights — Rafer Hazen (2024-08-14) canonicalises the Indexes tab on PlanetScale Insights as the productisation of a per-query-pattern index-usage time series. "The main graph shows a time series of the percentage of queries that use each index. The bar graph at the bottom shows cumulative usage over the entire time span." Canonical example: a query pattern where MySQL is "selecting from one of three indexes each time it executes" — a structural optimiser-flap shape the time-series visualisation makes visible in a way neither EXPLAIN nor performance_schema can.
Last updated · 470 distilled / 1,213 read