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: articles/cosmos-db/troubleshoot-query-performance.md
+34-26Lines changed: 34 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,42 +13,49 @@ ms.reviewer: sngun
13
13
14
14
This document walks through a general recommended approach for troubleshooting queries in Azure Cosmos DB. While the steps outlined in this document should not be considered a “catch all” for potential query issues, we have consolidated most performance tips here. You should use this document as a starting place for troubleshooting for Azure Cosmos DB’s core (SQL) API.
15
15
16
-
You can broadly categorize query optimizations in Azure Cosmos DB: Optimizations that reduce the Request Unit (RU) charge of the query and optimizations that just reduce latency. Of course, by reducing the RU charge of a query, you will almost certainly decrease latency as well.
16
+
You can broadly categorize query optimizations in Azure Cosmos DB: Optimizations that reduce the Request Unit (RU) charge of the query and optimizations that just reduce latency. By reducing the RU charge of a query, you will almost certainly decrease latency as well.
17
17
This document will use examples that can be recreated using the [nutrition](https://github.com/CosmosDB/labs/blob/master/dotnet/setup/NutritionData.json) data set.
18
18
19
19
You can reference the below section to understand the relevant query optimizations for your scenario:
20
20
21
21
### Query's RU charge is too high
22
22
23
-
**Loaded Document Count is significantly greater than Retrieved Document Count**
23
+
<br>
24
+
<br>
24
25
25
-
a. [Ensure that the indexing policy includes necessary paths](#Ensure-that-the-indexing-policy-includes-necessary-paths)
26
+
#### Loaded Document Count is significantly greater than Retrieved Document Count
26
27
27
-
b. [Understand which system functions utilize the index](#Understand-which-system-functions-utilize-the-index)
28
+
a. [Ensure that the indexing policy includes necessary paths](troubleshoot-query-performance.md#Ensure-that-the-indexing-policy-includes-necessary-paths)
28
29
29
-
c. [Optimize queries with both a filter and an ORDER BY clause](#Optimize-queries-with-both-a-filter-and-an-ORDER-BY-clause)
30
+
b. [Understand which system functions utilize the index](troubleshoot-query-performance.md#Understand-which-system-functions-utilize-the-index)
31
+
32
+
c. [Optimize queries with both a filter and an ORDER BY clause](troubleshoot-query-performance.md#Optimize-queries-with-both-a-filter-and-an-ORDER-BY-clause)
30
33
31
34
d. [Optimize queries that use DISTINCT](#Optimize-queries-that-use-DISTINCT)
32
35
33
-
e. [Optimize JOIN expressions by using a subquery](#Optimize-JOIN-expressions-by-using-a-subquery)
36
+
e. [Optimize JOIN expressions by using a subquery](troubleshoot-query-performance.md#Optimize-JOIN-expressions-by-using-a-subquery)
37
+
38
+
<br>
39
+
40
+
#### Loaded Document Count is approximately equal to Retrieved Document Count
34
41
35
-
**Loaded Document Count is approximately equal to Retrieved Document Count**
42
+
a. [Avoid cross partition queries](troubleshoot-query-performance.md#Avoid-cross-partition-queries)
36
43
37
-
a. [Avoid cross partition queries](#Avoid-cross-partition-queries)
44
+
b. [Optimize queries that have a filter on multiple properties](troubleshoot-query-performance.md#Optimize-queries-that-have-a-filter-on-multiple-properties)
38
45
39
-
b. [Optimize queries that have a filter on multiple properties](#Optimize-queries-that-have-a-filter-on-multiple-properties)
46
+
c. [Optimize queries with both a filter and an ORDER BY clause](troubleshoot-query-performance.md#Optimize-queries-with-both-a-filter-and-an-ORDER-BY-clause)
40
47
41
-
c. [Optimize queries with both a filter and an ORDER BY clause](#Optimize-queries-with-both-a-filter-and-an-ORDER-BY-clause)
48
+
<br>
42
49
43
50
### Query's RU charge is acceptable but latency is still too high
44
51
45
-
a. [Improving proximity between your app and Azure Cosmos DB](#Improving-proximity-between-your-app-and-Azure-Cosmos-DB)
52
+
a. [Improving proximity between your app and Azure Cosmos DB](troubleshoot-query-performance.md#Improving-proximity-between-your-app-and-Azure-Cosmos-DB)
46
53
47
-
b. [Increasing provisioned throughput](#Increasing-provisioned-throughput)
54
+
b. [Increasing provisioned throughput](troubleshoot-query-performance.md#Increasing-provisioned-throughput)
48
55
49
-
c. [Increasing MaxConcurrency](#Increasing-MaxConcurrency)
56
+
c. [Increasing MaxConcurrency](troubleshoot-query-performance.md#Increasing-MaxConcurrency)
50
57
51
-
d. [Increasing MaxBufferedItemCount](#Increasing-MaxBufferedItemCount)
58
+
d. [Increasing MaxBufferedItemCount](troubleshoot-query-performance.md#Increasing-MaxBufferedItemCount)
52
59
53
60
### Obtaining query metrics:
54
61
@@ -58,7 +65,7 @@ When optimizing a query in Azure Cosmos DB, the first step is always to [obtain
58
65
59
66
## Optimizations for queries where Loaded Document Count significantly exceeds Retrieved Document Count:
60
67
61
-
After obtaining query metrics, compare the Retrieved Document Count with the Loaded Document Count for your query. The Retrieved Document Count is the number of documents that will show up in the results of your query. The Loaded Document Count is the number of documents that needed to be scanned. If the Loaded Document Count is significantly higher than the Retrieved Document Count, then there was at least one part of your query which was unable to utilize the index.
68
+
After obtaining query metrics, compare the Retrieved Document Count with the Loaded Document Count for your query. The Retrieved Document Count is the number of documents that will show up in the results of your query. The Loaded Document Count is the number of documents that needed to be scanned. If the Loaded Document Count is significantly higher than the Retrieved Document Count, then there was at least one part of your query that was unable to utilize the index.
62
69
63
70
## Ensure that the indexing policy includes necessary paths
64
71
@@ -117,7 +124,7 @@ Updated indexing policy:
117
124
118
125
**RU Charge:** 2.98 RU's
119
126
120
-
You can add additional properties to the indexing policy at any time, with no impact to write availability or performance. If you add a new property to the index, queries that use this property will immediately utilize the new available index while it is being built. As a result, query results may be inconsistent as the index rebuild is in progress. If a new property is indexed, queries that only utilize existing indexes will not be affected during the index rebuild. You can [track index transformation progress](https://docs.microsoft.com/azure/cosmos-db/how-to-manage-indexing-policy#use-the-net-sdk-v3).
127
+
You can add additional properties to the indexing policy at any time, with no impact to write availability or performance. If you add a new property to the index, queries that use this property will immediately utilize the new available index. The query will utilize the new index while it is being built. As a result, query results may be inconsistent as the index rebuild is in progress. If a new property is indexed, queries that only utilize existing indexes will not be affected during the index rebuild. You can [track index transformation progress](https://docs.microsoft.com/azure/cosmos-db/how-to-manage-indexing-policy#use-the-net-sdk-v3).
121
128
122
129
## Understand which system functions utilize the index
123
130
@@ -133,7 +140,7 @@ Some common system functions that must load each document are shown below:
| CONTAINS | Use Azure Search for full text search |
135
142
| UPPER/LOWER | Instead of using the system function to normalize data each time for comparisons, instead normalize the casing upon insertion. Then a query such as ```SELECT * FROM c WHERE UPPER(c.name) = 'BOB'``` simply becomes ```SELECT * FROM c WHERE c.name = 'BOB'```|
136
-
| Mathematical functions (non-aggregates) | If you need to frequently compute a value in your query, consider storing this as a property in your JSON document. |
143
+
| Mathematical functions (non-aggregates) | If you need to frequently compute a value in your query, consider storing this value as a property in your JSON document. |
137
144
138
145
------
139
146
@@ -209,7 +216,7 @@ Updated indexing policy:
209
216
210
217
## Optimize queries that use DISTINCT
211
218
212
-
It will be more efficient to find the DISTINCT set of results if the duplicate results are consecutive. You can ensure that duplicate results are consecutive by adding an ORDER BY clause to the query and adding a composite index. If you need to ORDER BY multiple properties, add a composite index.
219
+
It will be more efficient to find the DISTINCT set of results if the duplicate results are consecutive. Adding an ORDER BY clause to the query and a composite index will ensure that duplicate results are consecutive. If you need to ORDER BY multiple properties, add a composite index.
213
220
214
221
### Original
215
222
@@ -280,12 +287,14 @@ Assume that only one item in the tags array matches the filter, and there are fi
280
287
281
288
## Optimizations for queries where Loaded Document Count is approximately equal to Retrieved Document Count:
282
289
283
-
If the Loaded Document Count is approximately equal to the Retrieved Document Count, it means the query did not have to scan a lot of unnecessary documents. For many queries, such as those that use the TOP keyword, Loaded Document Count may exceed Retrieved Document Count by 1. This should not be cause for concern.
290
+
If the Loaded Document Count is approximately equal to the Retrieved Document Count, it means the query did not have to scan many unnecessary documents. For many queries, such as those that use the TOP keyword, Loaded Document Count may exceed Retrieved Document Count by 1. This should not be cause for concern.
284
291
285
292
## Avoid cross partition queries
286
293
287
-
Azure Cosmos DB uses partitioning to scale individual containers as Request Unit and data storage needs increase. Each physical partition has a separate and independent index. If your query has an equality filter that matches your container’s partition key, you will only need to check relevant partition’s index. This reduces the total number of RU’s that the query requires.
288
-
If you have a large number of provisioned RU’s (over 30,000) or a large amount of data stored (over ~100 GB), you likely have a large enough container to see a significant reduction in query RU charges.
294
+
Azure Cosmos DB uses partitioning to scale individual containers as Request Unit and data storage needs increase. Each physical partition has a separate and independent index. If your query has an equality filter that matches your container’s partition key, you will only need to check the relevant partition’s index. This optimization reduces the total number of RU’s that the query requires.
295
+
296
+
If you have a large number of provisioned RU’s (over 30,000) or a large amount of data stored (over ~100 GB), you likely have a large enough container to see a significant reduction in query RU charges.
297
+
289
298
For example, if we create a container with the partition key foodGroup, the following queries would only need to check a single physical partition:
290
299
291
300
```sql
@@ -310,7 +319,7 @@ SELECT * FROM c WHERE c.foodGroup > “Soups, Sauces, and Gravies” and c.descr
310
319
311
320
## Optimize queries that have a filter on multiple properties
312
321
313
-
While queries with filters on multiple properties will normally utilize a range index, they will be more efficient if they can be served from a composite index. For small amounts of data this optimization will not have a significant impact. It may prove useful, however, with large amounts of data. You can only optimize, at most, one non-equality filter per composite index. If your query has multiple non-equality filters, you should pick one of them that will utilize the composite index. The remainder will continue to utilize range indexes. The non-equality filter must be defined last in the composite index.
322
+
While queries with filters on multiple properties will normally utilize a range index, they will be more efficient if they can be served from a composite index. For small amounts of data, this optimization will not have a significant impact. It may prove useful, however, with large amounts of data. You can only optimize, at most, one non-equality filter per composite index. If your query has multiple non-equality filters, you should pick one of them that will utilize the composite index. The remainder will continue to utilize range indexes. The non-equality filter must be defined last in the composite index.
314
323
315
324
Here are some examples of queries which could be optimized with a composite index:
316
325
@@ -355,19 +364,18 @@ In many cases, RU charge may be acceptable but query latency is still too high.
355
364
356
365
## Improving proximity between your app and Azure Cosmos DB
357
366
358
-
Queries that are run from outside the same Azure region as the Azure Cosmos DB account will have a higher latency than if they were run inside the same region. If, for example, you were running code on your desktop computer, you should expect latency to be tens or hundreds (or more) milliseconds greater than if the query came from a Virtual Machine within the same Azure region as Azure Cosmos DB. It is simple to globally distribute data in Azure Cosmos DB to ensure you can bring your data closer to your app.
367
+
Queries that are run from a different region than the Azure Cosmos DB account will have a higher latency than if they were run inside the same region. For example, if you were running code on your desktop computer, you should expect latency to be tens or hundreds (or more) milliseconds greater than if the query came from a Virtual Machine within the same Azure region as Azure Cosmos DB. It is simple to globally distribute data in Azure Cosmos DB to ensure you can bring your data closer to your app.
359
368
360
369
## Increasing provisioned throughput
361
370
362
-
In Azure Cosmos DB, your provisioned throughput is measured in Request Units (RU’s). Let’s imagine you have a query that consumes 5 RU’s of throughput. If you, for example, provision 1,000 RU’s, you would be able to run that query 200 times per second. If you attempted to run the query when there was not enough throughput available, Azure Cosmos DB would return a HTTP 429 error. Any of the current Core (SQL) API sdk’s will automatically retry this query after waiting a brief period. This will result in increased latency so increasing provisioned throughput can improve query latency.
363
-
You can observe the total number of throttled requests in the Metrics blade of the Azure Portal.
371
+
In Azure Cosmos DB, your provisioned throughput is measured in Request Units (RU’s). Let’s imagine you have a query that consumes 5 RU’s of throughput. For example, if you provision 1,000 RU’s, you would be able to run that query 200 times per second. If you attempted to run the query when there was not enough throughput available, Azure Cosmos DB would return an HTTP 429 error. Any of the current Core (SQL) API sdk's will automatically retry this query after waiting a brief period. Throttled requests take a longer amount of time, so increasing provisioned throughput can improve query latency. You can observe the [total number of requests throttled requests(use-metrics.md#understand-how-many-requests-are-succeeding-or-causing-errors in the Metrics blade of the Azure Portal.
364
372
365
373
## Increasing MaxConcurrency
366
374
Parallel queries work by querying multiple partitions in parallel. However, data from an individual partitioned collection is fetched serially with respect to the query. So, adjust the MaxConcurrency to set the number of partitions that has the maximum chance of achieving the most performant query, provided all other system conditions remain the same. If you don't know the number of partitions, you can set the MaxConcurrency (or MaxDegreesOfParallelism in older sdk versions) to set a high number, and the system chooses the minimum (number of partitions, user provided input) as the maximum degree of parallelism.
367
375
368
376
## Increasing MaxBufferedItemCount
369
377
370
-
Parallel query is designed to pre-fetch results while the current batch of results is being processed by the client. The pre-fetching helps in overall latency improvement of a query. Setting the MaxBufferedItemCount limits the number of pre-fetched results. By setting this value to the expected number of results returned (or a higher number), this enables the query to receive maximum benefit from pre-fetching.
378
+
Parallel query is designed to pre-fetch results while the current batch of results is being processed by the client. The pre-fetching helps in overall latency improvement of a query. Setting the MaxBufferedItemCount limits the number of pre-fetched results. By setting this value to the expected number of results returned (or a higher number), the query can receive maximum benefit from pre-fetching.
371
379
372
380
## Next steps
373
381
Refer to documents below on how to measure RUs per query, get execution statistics to tune your queries, and more:
0 commit comments