Query Store does not keep a separate index-usage ledger. It stores compiled Showplan XML and aggregated runtime statistics by plan and time interval. Search the plan XML for the index, then join runtime intervals to keep plans that recorded executions during the period you care about.
Last updated: October 7, 2026.
DECLARE @IndexName sysname = N'IX_Orders_CustomerId';
DECLARE @QuotedIndexName nvarchar(258) = QUOTENAME(@IndexName);
DECLARE @Since datetimeoffset = DATEADD(hour, -2, SYSUTCDATETIME());
SELECT q.query_id,
p.plan_id,
SUM(rs.count_executions) AS interval_executions,
qt.query_sql_text
FROM sys.query_store_plan AS p
JOIN sys.query_store_query AS q ON q.query_id = p.query_id
JOIN sys.query_store_query_text AS qt ON qt.query_text_id = q.query_text_id
CROSS APPLY (SELECT TRY_CONVERT(xml, p.query_plan) AS plan_xml) AS xp
JOIN sys.query_store_runtime_stats AS rs ON rs.plan_id = p.plan_id
JOIN sys.query_store_runtime_stats_interval AS rsi
ON rsi.runtime_stats_interval_id = rs.runtime_stats_interval_id
WHERE rsi.end_time > @Since
AND xp.plan_xml.exist('
declare default element namespace
"http://schemas.microsoft.com/sqlserver/2004/07/showplan";
//Object[@Index=sql:variable("@QuotedIndexName")]
') = 1
GROUP BY q.query_id, p.plan_id, qt.query_sql_text
ORDER BY interval_executions DESC;Run the query in the database whose Query Store you want to inspect. Showplan normally records the index as a bracketed identifier, so the example compares it with QUOTENAME(). If different schemas contain the same index name, add @Schema and @Table attribute tests to the XQuery.
Interpret the result as plan evidence
A matching plan references the index and has aggregated executions in an overlapping Query Store interval. It does not prove that every execution touched that operator: a plan can contain branches that were not taken, and runtime statistics are stored at the plan level rather than per operator. Confirm a critical finding with an actual execution plan, Extended Events, or targeted testing before changing the index.
Microsoft explains that Query Store saves compiled plans and interval-based runtime statistics. The interval boundary is not an exact per-execution timestamp.
Check all retained plans before dropping an index
Remove the time filter to search the full Query Store retention window, including older plans that are not currently active. Also check sys.dm_db_index_usage_stats, dependencies, maintenance jobs, reporting workloads, and code that runs less frequently than the retained window. A quiet two-hour period is not enough evidence that an index is unused.
Query Store may be read-only or may have evicted older data, so review its configuration and capture policy using Microsoft’s Query Store management guide. Continue with diagnosing Query Store plan variants, understanding SQL Server join selection, and SQL Server parameter behavior.