You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/relational-databases/performance/monitoring-performance-by-using-the-query-store.md
+45-5Lines changed: 45 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -57,7 +57,9 @@ manager: "jhubbard"
57
57
Execution plans for any specific query in [!INCLUDE[ssNoVersion](../../includes/ssnoversion-md.md)] typically evolve over time due to a number of different reasons such as statistics changes, schema changes, creation/deletion of indexes, etc. The procedure cache (where cached query plans are stored) only stores the latest execution plan. Plans also get evicted from the plan cache due to memory pressure. As a result, query performance regressions caused by execution plan changes can be non-trivial and time consuming to resolve.
58
58
59
59
Since the query store retains multiple execution plans per query, it can enforce policies to direct the query processor to use a specific execution plan for a query. This is referred to as plan forcing. Plan forcing in Query Store is provided by using a mechanism similar to the [USE PLAN](../../t-sql/queries/hints-transact-sql-query.md) query hint, but it does not require any change in user applications. Plan forcing can resolve a query performance regression caused by a plan change in a very short period of time.
60
-
60
+
61
+
**Wait stats** are another source of information that helps to troubleshoot performance in SQL Server. For a long time, wait statistics were available only on instance level, which made it hard to backtrack it to the actual query. In SQL Server 2017 and Azure SQL Database we added another dimension in Query Store that tracks wait stats.
62
+
61
63
Common scenarios for using the Query Store feature are:
62
64
63
65
- Quickly find and fix a plan performance regression by forcing the previous query plan. Fix queries that have recently regressed in performance due to execution plan changes.
@@ -69,8 +71,15 @@ manager: "jhubbard"
69
71
- Audit the history of query plans for a given query.
70
72
71
73
- Analyze the resource (CPU, I/O, and Memory) usage patterns for a particular database.
74
+
- Identify top n queries that are waiting on resources.
75
+
- Understand wait nature for a particular query or plan.
72
76
73
-
The query store contains two stores; a **plan store** for persisting the execution plan information, and a **runtime stats store** for persisting the execution statistics information. The number of unique plans that can be stored for a query in the plan store is limited by the **max_plans_per_query** configuration option. To enhance performance, the information is written to the two stores asynchronously. To minimize space usage, the runtime execution statistics in the runtime stats store are aggregated over a fixed time window. The information in these stores is visible by querying the query store catalog views.
77
+
The query store contains three stores:
78
+
- a **plan store** for persisting the execution plan information
79
+
- a **runtime stats store** for persisting the execution statistics information.
80
+
- a **wait stats store** for persisting wait statistics information.
81
+
82
+
The number of unique plans that can be stored for a query in the plan store is limited by the **max_plans_per_query** configuration option. To enhance performance, the information is written to the two stores asynchronously. To minimize space usage, the runtime execution statistics in the runtime stats store are aggregated over a fixed time window. The information in these stores is visible by querying the query store catalog views.
74
83
75
84
The following query returns information about queries and plans in the query store.
76
85
@@ -93,7 +102,21 @@ JOIN sys.query_store_query_text AS Txt
93
102

94
103
95
104
To force a plan, select a query and plan, and then click **Force Plan**. You can only force plans that were saved by the query plan feature and are still retained in the query plan cache.
96
-
105
+
## <aname="Waiting"></a> Finding wait queries
106
+
107
+
Starting from SQL Server 2017 CTP 2.0 and on Azure SQL Database wait statistics per query over time are available for Query Store customers.
108
+
In Query Store wait types are combined into **wait categories**. Full mapping is available here [sys.query_store_wait_stats (Transact-SQL)](../../relational-databases/system-catalog-views/sys-query-store-wait-stats-transact-sql.md)
109
+
110
+
**Wait categories** are combining different wait types into buckets similar by nature. Different wait categories require a different follow up analysis to resolve the issue, but wait types from the same category lead to very similar troubleshooting experiences, and providing the affected query on top of waits would be the missing piece to complete the majority of such investigations successfully.
111
+
112
+
Here are some examples how you can get more insights into your workload before and after introducing wait categories in Query Store:
113
+
||||
114
+
|-|-|-|
115
+
|Previous experience|New experience|Action|
116
+
|High RESOURCE_SEMAPHORE waits per database|High Memory waits in Query Store for specific queries|Find the top memory consuming queries in Query Store. These queries are probably delaying further progress of the affected queries. Consider using MAX_GRANT_PERCENT query hint for these queries, or for the affected queries.|
117
+
|High LCK_M_X waits per database|High Lock waits in Query Store for specific queries|Check the query texts for the affected queries and identify the target entities. Look in Query Store for other queries modifying the same entity, which are executed frequently and/or have high duration. After identifying these queries, consider changing the application logic to improve concurrency, or use a less restrictive isolation level.|
118
+
|High PAGEIOLATCH_SH waits per database|High Buffer IO waits in Query Store for specific queries|Find the queries with a high number of physical reads in Query Store. If they match the queries with high IO waits, consider introducing an index on the underlying entity, in order to do seeks instead of scans, and thus minimize the IO overhead of the queries.|
119
+
|High SOS_SCHEDULER_YIELD waits per database|High CPU waits in Query Store for specific queries|Find the top CPU consuming queries in Query Store. Among them, identify the queries for which high CPU trend correlates with high CPU waits for the affected queries. Focus on optimizing those queries – there could be a plan regression, or perhaps a missing index.|
97
120
## <aname="Options"></a> Configuration Options
98
121
99
122
The following options are available to configure query store parameters.
@@ -227,7 +250,8 @@ SET QUERY_STORE (
227
250
INTERVAL_LENGTH_MINUTES = 15,
228
251
SIZE_BASED_CLEANUP_MODE = AUTO,
229
252
QUERY_CAPTURE_MODE = AUTO,
230
-
MAX_PLANS_PER_QUERY = 1000
253
+
MAX_PLANS_PER_QUERY = 1000,
254
+
WAIT_STATS_CAPTURE_MODE = ON
231
255
);
232
256
```
233
257
@@ -418,7 +442,23 @@ ORDER BY q.query_id, rsi1.start_time, rsi2.start_time;
418
442
```
419
443
420
444
If you want to see performance all regressions (not only those related to plan choice change) than just remove condition `AND p1.plan_id <> p2.plan_id` from the previous query.
421
-
445
+
446
+
**Queries that are waiting the most?**
447
+
This query will return top 10 queries that wait the most.
448
+
```tsql
449
+
SELECT TOP 10
450
+
qt.query_text_id,
451
+
q.query_id,
452
+
p.plan_id,
453
+
sum(total_query_wait_time_ms) AS sum_total_wait_ms
454
+
FROM sys.query_store_wait_stats ws
455
+
JOIN sys.query_store_plan p ON ws.plan_id = p.plan_id
456
+
JOIN sys.query_store_query q ON p.query_id = q.query_id
457
+
JOIN sys.query_store_query_text qt ON q.query_text_id = qt.query_text_id
458
+
GROUP BY qt.query_text_id, q.query_id, p.plan_id
459
+
ORDER BY sum_total_wait_ms DESC
460
+
```
461
+
422
462
**Queries that recently regressed in performance (comparing recent vs. history execution)?** The next query compares query execution based periods of execution. In this particular example the query compares execution in recent period (1 hour) vs. history period (last day) and identifies those that introduced `additional_duration_workload`. This metrics is calculated as a difference between recent average execution and history average execution multiplied by the number of recent executions. It actually represents how much of additional duration recent executions introduced compared to history:
0 commit comments