Events
Mar 31, 11 PM - Apr 2, 11 PM
The biggest SQL, Fabric and Power BI learning event. March 31 – April 2. Use code FABINSIDER to save $400.
Register todayThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Applies to:
SQL Server
Azure SQL Database
Azure SQL Managed Instance
This article outlines the management of the SQL Server Query Store and the surrounding features.
Note
In SQL Server 2022 (16.x), Query Store is now enabled by default for all newly created SQL Server databases to help better track performance history, troubleshoot query plan–related issues, and enable new query processor capabilities.
This section describes optimal configuration defaults in Azure SQL Database that are designed to ensure reliable operation of the Query Store and dependent features. Default configuration is optimized for continuous data collection, that is minimal time spent in OFF/READ_ONLY states. For more information about all available Query Store options, see ALTER DATABASE SET options (Transact-SQL).
Configuration | Description | Default | Comment |
---|---|---|---|
MAX_STORAGE_SIZE_MB | Specifies the limit for the data space that Query Store can take inside the customer database | 100 prior to SQL Server 2019 (15.x) 1000 starting with SQL Server 2019 (15.x) |
Enforced for new databases |
INTERVAL_LENGTH_MINUTES | Defines size of time window during which collected runtime statistics for query plans are aggregated and persisted. Every active query plan has at most one row for a period of time defined with this configuration | 60 | Enforced for new databases |
STALE_QUERY_THRESHOLD_DAYS | Time-based cleanup policy that controls the retention period of persisted runtime statistics and inactive queries | 30 | Enforced for new databases and databases with previous default (367) |
SIZE_BASED_CLEANUP_MODE | Specifies whether automatic data cleanup takes place when Query Store data size approaches the limit | AUTO | Enforced for all databases |
QUERY_CAPTURE_MODE | Specifies whether all queries or only a subset of queries are tracked | AUTO | Enforced for all databases |
DATA_FLUSH_INTERVAL_SECONDS | Specifies maximum period during which captured runtime statistics are kept in memory, before flushing to disk | 900 | Enforced for new databases |
Important
These defaults are automatically applied in the final stage of Query Store activation in an Azure SQL Database. After it's enabled, Azure SQL Database won't change configuration values that are set by customers, unless they negatively impact primary workload or reliable operations of the Query Store.
Note
Query Store cannot be disabled in Azure SQL Database single database and Elastic Pool. Executing ALTER DATABASE [database] SET QUERY_STORE = OFF
will return the warning 'QUERY_STORE=OFF' is not supported in this version of SQL Server.
If you want to stay with your custom settings, use ALTER DATABASE with Query Store options to revert configuration to the previous state. Check out Best Practices with the Query Store in order to learn how to choose optimal configuration parameters.
Keep the most relevant data in Query Store. The following table describes typical scenarios for each Query Store Capture Mode:
Query Store Capture Mode | Scenario |
---|---|
All | Analyze your workload thoroughly in terms of all queries' shapes and their execution frequencies and other statistics. Identify new queries in your workload. Detect if ad hoc queries are used to identify opportunities for user or auto parameterization. Note: This is the default capture mode in SQL Server 2016 (13.x) and SQL Server 2017 (14.x). |
Auto | Focus your attention on relevant and actionable queries. An example is those queries that execute regularly or that have significant resource consumption. Note: In SQL Server 2019 (15.x) and later versions this is the default capture mode. |
None | You've already captured the query set that you want to monitor in runtime and you want to eliminate the distractions that other queries might introduce. None is suitable for testing and benchmarking environments. None is also appropriate for software vendors who ship Query Store configuration configured to monitor their application workload. None should be used with caution because you might miss the opportunity to track and optimize important new queries. Avoid using None unless you have a specific scenario that requires it. |
Custom | SQL Server 2019 (15.x) introduced a custom capture mode under the ALTER DATABASE ... SET QUERY_STORE command. While Auto is default and recommended, if there is still any concern about the overhead Query Store might introduce, database administrators can use custom capture policies to further tune the Query Store capture behavior. For more information and recommendations, see Custom capture policies later in this article. For more information on this syntax, see ALTER DATABASE SET Options. |
Note
Cursors, queries inside stored procedures, and natively compiled queries are always captured when Query Store Capture Mode is set to All, Auto, or Custom. To capture natively compiled queries, enable collection of per-query statistics by using sys.sp_xtp_control_query_exec_stats.
Configure Query Store to contain only the relevant data so that it runs continuously and provides a great troubleshooting experience with a minimal impact on your regular workload.
The following table provides best practices:
Best practice | Setting |
---|---|
Limit retained historical data. | Configure time-based policy to activate autocleanup. |
Filter out nonrelevant queries. | Configure Query Store Capture Mode to Auto. |
Delete less relevant queries when the maximum size is reached. | Activate size-based cleanup policy. |
When the CUSTOM Query Store Capture Mode is enabled, additional Query Store configurations are available under a new Query Store capture policy setting to fine-tune data collection in a specific server.
The new custom settings define what happens during the internal capture policy time threshold. This is a time boundary during which the configurable conditions are evaluated and, if any are true, the query is eligible to be captured by Query Store.
The Query Store Capture Mode specifies the query capture policy for Query Store.
Tuning an appropriate custom capture policy for your environment should be considered when:
Download the latest version of SQL Server Management Studio (SSMS)
To view current settings in Management Studio:
The following example sets QUERY_CAPTURE_MODE to AUTO and sets a custom capture mode. Each of the following sets the custom capture policies to its default value in SQL Server 2022 (16.x). Consider adjusting these values to reduce the number of queries captured, and therefore reduce the on-disk footprint of the Query Store. It is recommended to gradually change these values by small increments.
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE = ON
(
OPERATION_MODE = READ_WRITE,
CLEANUP_POLICY = ( STALE_QUERY_THRESHOLD_DAYS = 90 ),
DATA_FLUSH_INTERVAL_SECONDS = 900,
MAX_STORAGE_SIZE_MB = 1000,
INTERVAL_LENGTH_MINUTES = 60,
SIZE_BASED_CLEANUP_MODE = AUTO,
QUERY_CAPTURE_MODE = CUSTOM,
QUERY_CAPTURE_POLICY = (
STALE_CAPTURE_POLICY_THRESHOLD = 24 HOURS,
EXECUTION_COUNT = 30,
TOTAL_COMPILE_CPU_TIME_MS = 1000,
TOTAL_EXECUTION_CPU_TIME_MS = 100
)
);
The following sample query alters an existing Query Store to use a custom capture policy that overrides the default settings for EXECUTION_COUNT
and TOTAL_COMPILE_CPU_TIME_MS
.
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE = ON
(
QUERY_CAPTURE_MODE = CUSTOM,
QUERY_CAPTURE_POLICY = (
EXECUTION_COUNT = 100,
TOTAL_COMPILE_CPU_TIME_MS = 10000
)
);
The default maximum size value of the Query Store is 1000 MB, starting in SQL Server 2019 (15.x). In previous versions, the default was 100 MB. Increasing the maximum size limit of the Query Store is appropriate in a busy database with many unique query plans. Adjusting the capture policy (see previous section) is a more important consideration to limit the on-disk size of the Query Store and to prevent the Query Store from entering READ_ONLY mode. While Query Store collects queries, execution plans, and statistics, its size in the database grows until this limit is reached. When that happens, Query Store automatically changes the operation mode to READ_ONLY and stops collecting new data, which means that your performance analysis is no longer accurate.
MAX_STORAGE_SIZE_MB
limit isn't strictly enforced.MAX_STORAGE_SIZE_MB
value is 10,240 MB.Storage size is checked only when Query Store writes data to disk. This interval is set by the DATA_FLUSH_INTERVAL_SECONDS
option or the Management Studio Query Store dialog option Data Flush Interval.
MAX_STORAGE_SIZE_MB
limit between storage size checks, it transitions to read-only mode.SIZE_BASED_CLEANUP_MODE
is enabled, the cleanup mechanism to enforce the MAX_STORAGE_SIZE_MB
limit is also triggered.
For more information, see ALTER DATABASE SET OPTION MAX_STORAGE_SIZE_MB.
The Data Flush Interval defines the frequency before collected runtime statistics are persisted to disk. In SQL Server Management Studio, the value is in minutes, but in Transact-SQL it's expressed in seconds. The default is 15 minutes (900 seconds).
Note
Using trace flag 7745 prevents Query Store data from being written to disk in case of a failover or shutdown command. For more information, see Use Query Store in mission-critical servers.
Configure Query Store based on your workload and performance troubleshooting requirements. The default parameters are good enough to start, but you should monitor how Query Store behaves over time and adjust its configuration accordingly.
View the current Query Store settings in SQL Server Management Studio (SSMS) or T-SQL.
Download the latest version of SQL Server Management Studio (SSMS)
To view current settings in Management Studio:
The following script sets a new value for Max Size (MB):
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE (MAX_STORAGE_SIZE_MB = 1024);
Use SQL Server Management Studio or Transact-SQL to set a different value for Data Flush Interval:
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE (DATA_FLUSH_INTERVAL_SECONDS = 900);
Statistics Collection Interval: Defines the level of granularity for the collected runtime statistic, expressed in minutes. The default is 60 minutes. Consider using a lower value if you require finer granularity or less time to detect and mitigate issues. Keep in mind that the value directly affects the size of Query Store data. Use SQL Server Management Studio or Transact-SQL to set a different value for Statistics Collection Interval:
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE (INTERVAL_LENGTH_MINUTES = 60);
Stale Query Threshold (Days): Time-based cleanup policy that controls the retention period of persisted runtime statistics and inactive queries, expressed in days. By default, Query Store is configured to keep the data for 30 days, which might be unnecessarily long for your scenario.
Avoid keeping historical data that you don't plan to use. This practice reduces changes to read-only status. The size of Query Store data and the time to detect and mitigate the issue will be more predictable. Use Management Studio or the following script to configure time-based cleanup policy:
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE (CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 90));
Size Based Cleanup Mode: Specifies whether automatic data cleanup takes place when Query Store data size approaches the limit. Activate size-based cleanup to make sure that Query Store always runs in read-write mode and collects the latest data. There's no guarantee under heavy workloads that Query Store cleanup will consistently maintain the data size under the limit. It's possible for the automatic data cleanup to fall behind and to switch (temporarily) into read-only mode.
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE (SIZE_BASED_CLEANUP_MODE = AUTO);
Query Store Capture Mode: Specifies the query capture policy for Query Store.
Important
Cursors, queries inside stored procedures, and natively compiled queries are always captured when Query Store Capture Mode is set to All, Auto, or Custom. To capture natively compiled queries, enable collection of per-query statistics by using sys.sp_xtp_control_query_exec_stats.
The following script sets QUERY_CAPTURE_MODE to AUTO:
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE (QUERY_CAPTURE_MODE = AUTO);
The following example sets QUERY_CAPTURE_MODE to AUTO and sets other recommended options in SQL Server 2016 (13.x):
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE = ON
(
OPERATION_MODE = READ_WRITE,
CLEANUP_POLICY = ( STALE_QUERY_THRESHOLD_DAYS = 90 ),
DATA_FLUSH_INTERVAL_SECONDS = 900,
QUERY_CAPTURE_MODE = AUTO,
MAX_STORAGE_SIZE_MB = 1000,
INTERVAL_LENGTH_MINUTES = 60
);
The following example sets QUERY_CAPTURE_MODE to AUTO and sets other recommended options in SQL Server 2017 (14.x) to include wait statistics:
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE = ON
(
OPERATION_MODE = READ_WRITE,
CLEANUP_POLICY = ( STALE_QUERY_THRESHOLD_DAYS = 90 ),
DATA_FLUSH_INTERVAL_SECONDS = 900,
QUERY_CAPTURE_MODE = AUTO,
MAX_STORAGE_SIZE_MB = 1000,
INTERVAL_LENGTH_MINUTES = 60,
SIZE_BASED_CLEANUP_MODE = AUTO,
MAX_PLANS_PER_QUERY = 200,
WAIT_STATS_CAPTURE_MODE = ON
);
The following example sets the CUSTOM capture policy to the SQL Server 2019 (15.x) defaults, instead of the new default AUTO capture mode. For more information on custom capture policy options and defaults, see <query_capture_policy_option_list>.
ALTER DATABASE [QueryStoreDB]
SET QUERY_STORE = ON
(
OPERATION_MODE = READ_WRITE,
CLEANUP_POLICY = ( STALE_QUERY_THRESHOLD_DAYS = 90 ),
DATA_FLUSH_INTERVAL_SECONDS = 900,
MAX_STORAGE_SIZE_MB = 1000,
INTERVAL_LENGTH_MINUTES = 60,
SIZE_BASED_CLEANUP_MODE = AUTO,
MAX_PLANS_PER_QUERY = 200,
WAIT_STATS_CAPTURE_MODE = ON,
QUERY_CAPTURE_MODE = CUSTOM,
QUERY_CAPTURE_POLICY = (
STALE_CAPTURE_POLICY_THRESHOLD = 24 HOURS,
EXECUTION_COUNT = 30,
TOTAL_COMPILE_CPU_TIME_MS = 1000,
TOTAL_EXECUTION_CPU_TIME_MS = 100
)
);
This section provides some guidelines on managing Query Store feature itself.
Query Store stores its data inside the user database and that is why it has size limit (configured with MAX_STORAGE_SIZE_MB
). If data in Query Store hits that limit Query Store will automatically change state from read-write to read-only and stop collecting new data.
Query sys.database_query_store_options to determine if Query Store is currently active, and whether it is currently collects runtime stats or not.
SELECT actual_state, actual_state_desc, readonly_reason,
current_storage_size_mb, max_storage_size_mb
FROM sys.database_query_store_options;
Query Store status is determined by the actual_state
column. If it's different than the desired status, the readonly_reason
column can give you more information. When Query Store size exceeds the quota, the feature will switch to read_only mode and provide a reason. For information on reasons, see sys.database_query_store_options.
To find out detailed information about Query Store status, execute following in a user database.
SELECT * FROM sys.database_query_store_options;
You can override interval for aggregating query runtime statistics (default is 60 minutes). New value for interval is exposed through sys.database_query_store_options
view.
ALTER DATABASE <database_name>
SET QUERY_STORE (INTERVAL_LENGTH_MINUTES = 15);
Arbitrary values are not allowed for INTERVAL_LENGTH_MINUTES
. Use one of the following intervals: 1, 5, 10, 15, 30, 60, or 1440 minutes.
Note
For Azure Synapse Analytics, customizing Query Store configuration options, as demonstrated in this section, is not supported.
To check current the Query Store size and limit execute the following statement in the user database.
SELECT current_storage_size_mb, max_storage_size_mb
FROM sys.database_query_store_options;
If the Query Store storage is full use the following statement to extend the storage.
ALTER DATABASE <database_name>
SET QUERY_STORE (MAX_STORAGE_SIZE_MB = <new_size>);
You can set multiple Query Store options at once with a single ALTER DATABASE statement.
ALTER DATABASE <database name>
SET QUERY_STORE (
OPERATION_MODE = READ_WRITE,
CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 30),
DATA_FLUSH_INTERVAL_SECONDS = 3000,
MAX_STORAGE_SIZE_MB = 500,
INTERVAL_LENGTH_MINUTES = 15,
SIZE_BASED_CLEANUP_MODE = AUTO,
QUERY_CAPTURE_MODE = AUTO,
MAX_PLANS_PER_QUERY = 1000,
WAIT_STATS_CAPTURE_MODE = ON
);
For the full list of configuration options, see ALTER DATABASE SET Options (Transact-SQL).
Query Store internal tables are created in the PRIMARY filegroup during database creation and that configuration cannot be changed later. If you are running out of space, you might want to clear older Query Store data by using the following statement.
ALTER DATABASE <db_name> SET QUERY_STORE CLEAR;
Alternatively, you might want to clear up only ad hoc query data, since it is less relevant for query optimizations and plan analysis but takes up just as much space.
In Azure Synapse Analytics, clearing the Query Store is not available. Data is automatically retained for the past seven days.
This purges ad hoc and internal queries from the Query Store so that the Query Store does not run out of space and remove queries we really need to track.
SET NOCOUNT ON
-- This purges adhoc and internal queries from
-- the Query Store in the current database
-- so that the Query Store does not run out of space
-- and remove queries we really need to track
DECLARE @id int;
DECLARE adhoc_queries_cursor CURSOR
FOR
SELECT q.query_id
FROM sys.query_store_query_text AS qt
JOIN sys.query_store_query AS q
ON q.query_text_id = qt.query_text_id
JOIN sys.query_store_plan AS p
ON p.query_id = q.query_id
JOIN sys.query_store_runtime_stats AS rs
ON rs.plan_id = p.plan_id
WHERE q.is_internal_query = 1 -- is it an internal query then we dont care to keep track of it
OR q.object_id = 0 -- if it does not have a valid object_id then it is an adhoc query and we don't care about keeping track of it
GROUP BY q.query_id
HAVING MAX(rs.last_execution_time) < DATEADD (minute, -5, GETUTCDATE()) -- if it has been more than 5 minutes since the adhoc query ran
ORDER BY q.query_id;
OPEN adhoc_queries_cursor ;
FETCH NEXT FROM adhoc_queries_cursor INTO @id;
WHILE @@fetch_status = 0
BEGIN
PRINT 'EXEC sp_query_store_remove_query ' + str(@id);
EXEC sp_query_store_remove_query @id;
FETCH NEXT FROM adhoc_queries_cursor INTO @id;
END
CLOSE adhoc_queries_cursor;
DEALLOCATE adhoc_queries_cursor;
You can define your own procedure with different logic for clearing up data you no longer want.
The previous example uses the sp_query_store_remove_query
extended stored procedure for removing unnecessary data. You can also:
sp_query_store_reset_exec_stats
to clear runtime statistics for a given plan.sp_query_store_remove_plan
to remove a single plan.Events
Mar 31, 11 PM - Apr 2, 11 PM
The biggest SQL, Fabric and Power BI learning event. March 31 – April 2. Use code FABINSIDER to save $400.
Register todayTraining
Documentation
Best practices for monitoring workloads with Query Store - SQL Server
Learn best practices for using SQL Server Query Store with your workload, such as using the latest SQL Server Management Studio and Query Performance Insight.
Monitor performance by using the Query Store - SQL Server
Query Store provides insight on query plan choice and performance for SQL Server, Azure SQL Database, Azure SQL Managed Instance, and Azure Synapse Analytics. Query Store captures history of queries, plans, and runtime statistics.
How Query Store collects data - SQL Server
SQL Server Query Store persists query-related data in the internal tables and presents it to users through a set of views.