Azure Cosmos DB を使用する場合のクエリの問題のトラブルシューティングTroubleshoot query issues when using Azure Cosmos DB

適用対象: SQL API

この記事では、Azure Cosmos DB のクエリのトラブルシューティングに関する一般的な推奨アプローチについて説明します。This article walks through a general recommended approach for troubleshooting queries in Azure Cosmos DB. この記事で説明されている手順により、クエリで発生する可能性がある問題を完全に防ぐことができると考えてはいけませんが、パフォーマンスに関する最も一般的なヒントを示してあります。Although you shouldn't consider the steps outlined in this article a complete defense against potential query issues, we've included the most common performance tips here. この記事は、Azure Cosmos DB Core (SQL) API の低速クエリまたはコストの高いクエリのトラブルシューティングのための出発点として使用してください。You should use this article as a starting place for troubleshooting slow or expensive queries in the Azure Cosmos DB core (SQL) API. また、診断ログを使用して、遅いクエリやスループットの消費量が多いクエリを特定することもできます。You can also use diagnostics logs to identify queries that are slow or that consume significant amounts of throughput. Azure Cosmos DB の MongoDB 用 API を使用する場合、Azure Cosmos DB の MongoDB 用 API クエリのトラブルシューティング ガイドをご利用ください。If you are using Azure Cosmos DB's API for MongoDB, you should use Azure Cosmos DB's API for MongoDB query troubleshooting guide

Azure Cosmos DB でのクエリの最適化は、次のように大きく分類されています。Query optimizations in Azure Cosmos DB are broadly categorized as follows:

  • クエリの要求ユニット (RU) 使用量を削減する最適化Optimizations that reduce the Request Unit (RU) charge of the query
  • クエリの待機時間を短縮するだけの最適化Optimizations that just reduce latency

クエリの RU 使用量を減らすと、一般的に待機時間も短くなります。If you reduce the RU charge of a query, you'll typically decrease latency as well.

この記事では、栄養データセットを使用して再作成できる例を示します。This article provides examples that you can re-create by using the nutrition dataset.

SDK に関する一般的な問題Common SDK issues

このガイドを読む前に、クエリ エンジンに関連しない一般的な SDK の問題について検討することをお勧めします。Before reading this guide, it is helpful to consider common SDK issues that aren't related to the query engine.

  • これらの SDK パフォーマンスのヒントに従ってください。Follow these SDK Performance tips.
  • SDK では、クエリの MaxItemCount を設定できますが、最小項目数は指定できません。The SDK allows setting a MaxItemCount for your queries but you can't specify a minimum item count.
    • コードで、0 から MaxItemCount までのすべてのページ サイズを処理する必要があります。Code should handle any page size, from zero to the MaxItemCount.
  • 将来のページには結果がある場合でも、クエリで空のページを受け取ることがあります。Sometimes queries may have empty pages even when there are results on a future page. これには、次のような理由が考えられます。Reasons for this could be:
    • SDK が複数のネットワーク呼び出しを実行している可能性があります。The SDK could be doing multiple network calls.
    • クエリでドキュメントを取得するのに時間がかかっている可能性があります。The query might be taking a long time to retrieve the documents.
  • すべてのクエリには、クエリの続行を許可する継続トークンがあります。All queries have a continuation token that will allow the query to continue. 必ず、クエリを完全にドレインするようにしてください。Be sure to drain the query completely. 複数にわたる結果のページの処理に関するページをご覧くださいLearn more about handling multiple pages of results

クエリのメトリックを取得するGet query metrics

Azure Cosmos DB でクエリを最適化する場合、最初の手順は常にクエリのクエリ メトリックを取得することです。When you optimize a query in Azure Cosmos DB, the first step is always to get the query metrics for your query. これらのメトリックは、Azure portal からも入手できます。These metrics are also available through the Azure portal. Data Explorer でクエリを実行すると、 [結果] タブの横にクエリ メトリックが表示されます。Once you run your query in the Data Explorer, the query metrics are visible next to the Results tab:

クエリ メトリックの取得

クエリ メトリックを取得した後、クエリの [取得したドキュメント数][出力したドキュメント数] を比較します。After you get the query metrics, compare the Retrieved Document Count with the Output Document Count for your query. この比較により、この記事で確認する関連セクションを特定します。Use this comparison to identify the relevant sections to review in this article.

[取得したドキュメント数] は、クエリ エンジンが読み込む必要があったドキュメントの数です。The Retrieved Document Count is the number of documents that the query engine needed to load. [出力したドキュメント数] は、クエリの結果に必要だったドキュメントの数です。The Output Document Count is the number of documents that were needed for the results of the query. [取得したドキュメント数][出力したドキュメント数] より大幅に多い場合は、クエリの少なくとも 1 つの部分でインデックスを使用できず、スキャンを実行する必要がありました。If the Retrieved Document Count is significantly higher than the Output Document Count, there was at least one part of your query that was unable to use an index and needed to do a scan.

シナリオに関連するクエリの最適化について理解するには、以下のセクションを参照してください。Refer to the following sections to understand the relevant query optimizations for your scenario.

クエリの RU 使用量が高すぎるQuery's RU charge is too high

取得したドキュメント数が出力したドキュメント数を大幅に超えているRetrieved Document Count is significantly higher than Output Document Count


取得したドキュメント数が出力したドキュメント数とほぼ等しいRetrieved Document Count is approximately equal to Output Document Count


クエリの RU 使用量は許容されるが、待機時間は依然として長すぎるQuery's RU charge is acceptable but latency is still too high

取得したドキュメント数が出力したドキュメント数を超えるクエリQueries where Retrieved Document Count exceeds Output Document Count

[取得したドキュメント数] は、クエリ エンジンが読み込む必要があったドキュメントの数です。The Retrieved Document Count is the number of documents that the query engine needed to load. [出力したドキュメント数] は、クエリによって返されたドキュメントの数です。The Output Document Count is the number of documents returned by the query. [取得したドキュメント数][出力したドキュメント数] より大幅に多い場合は、クエリの少なくとも 1 つの部分でインデックスを使用できず、スキャンを実行する必要がありました。If the Retrieved Document Count is significantly higher than the Output Document Count, there was at least one part of your query that was unable to use an index and needed to do a scan.

インデックスによって完全には処理されなかったスキャン クエリの例を次に示します。Here's an example of scan query that wasn't entirely served by the index:

クエリ:Query:

SELECT VALUE c.description
FROM c
WHERE UPPER(c.description) = "BABYFOOD, DESSERT, FRUIT DESSERT, WITHOUT ASCORBIC ACID, JUNIOR"

クエリ メトリック:Query metrics:

Retrieved Document Count                 :          60,951
Retrieved Document Size                  :     399,998,938 bytes
Output Document Count                    :               7
Output Document Size                     :             510 bytes
Index Utilization                        :            0.00 %
Total Query Execution Time               :        4,500.34 milliseconds
  Query Preparation Times
    Query Compilation Time               :            0.09 milliseconds
    Logical Plan Build Time              :            0.05 milliseconds
    Physical Plan Build Time             :            0.04 milliseconds
    Query Optimization Time              :            0.01 milliseconds
  Index Lookup Time                      :            0.01 milliseconds
  Document Load Time                     :        4,177.66 milliseconds
  Runtime Execution Times
    Query Engine Times                   :          322.16 milliseconds
    System Function Execution Time       :           85.74 milliseconds
    User-defined Function Execution Time :            0.00 milliseconds
  Document Write Time                    :            0.01 milliseconds
Client Side Metrics
  Retry Count                            :               0
  Request Charge                         :        4,059.95 RUs

[取得したドキュメント数] (60,951) は、 [出力したドキュメント数] (7) を大幅に上回っており、このクエリの結果としてドキュメントのスキャンが行われたことを示しています。The Retrieved Document Count (60,951) is significantly higher than the Output Document Count (7), implying that this query resulted in a document scan. この場合、システム関数 UPPER() ではインデックスは使用されません。In this case, the system function UPPER() doesn't use an index.

インデックス作成ポリシーに必要なパスを含めるInclude necessary paths in the indexing policy

インデックス作成ポリシーでは、WHERE 句、ORDER BY 句、JOIN、およびほとんどのシステム関数に含まれるすべてのプロパティがカバーされている必要があります。Your indexing policy should cover any properties included in WHERE clauses, ORDER BY clauses, JOIN, and most system functions. インデックス ポリシーに指定された必要なパスは、JSON ドキュメント内のプロパティと一致している必要があります。The desired paths specified in the index policy should match the properties in the JSON documents.

注意

Azure Cosmos DB のインデックス作成ポリシーのプロパティでは、大文字と小文字が区別されます。Properties in Azure Cosmos DB indexing policy are case-sensitive

栄養データセットに対して次の単純なクエリを実行する場合、WHERE 句のプロパティのインデックスが作成されると RU 料金がはるかに低くなります。If you run the following simple query on the nutrition dataset, you will observe a much lower RU charge when the property in the WHERE clause is indexed:

変更元Original

クエリ:Query:

SELECT *
FROM c
WHERE c.description = "Malabar spinach, cooked"

インデックス作成ポリシー:Indexing policy:

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/*"
        }
    ],
    "excludedPaths": [
        {
            "path": "/description/*"
        }
    ]
}

RU 使用量: 409.51 RURU charge: 409.51 RUs

最適化Optimized

更新されたインデックス作成ポリシー:Updated indexing policy:

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/*"
        }
    ],
    "excludedPaths": []
}

RU 使用量: 2.98 RURU charge: 2.98 RUs

書き込みまたは読み取りの可用性に影響を与えることなく、いつでもインデックス作成ポリシーにプロパティを追加できます。You can add properties to the indexing policy at any time, with no effect on write or read availability. インデックス変換の進行状況を追跡できます。You can track index transformation progress.

インデックスを使用するシステム関数について理解するUnderstand which system functions use the index

ほとんどのシステム関数では、インデックスが使用されます。Most system functions use indexes. インデックスを使用する一般的な文字列関数の一覧を次に示します。Here's a list of some common string functions that use indexes:

  • StartsWithStartsWith
  • ContainsContains
  • RegexMatchRegexMatch
  • LeftLeft
  • Substring - ただし、最初の num_expr が 0 の場合のみSubstring - but only if the first num_expr is 0

WHERE 句で使用されたときに、インデックスを使用せず、各ドキュメントを読み込む必要がある一般的なシステム関数は、次のとおりです。Following are some common system functions that don't use the index and must load each document when used in a WHERE clause:

システム関数System function 最適化のアイデアIdeas for optimization
UPPER/LOWERUpper/Lower システム関数を使用して比較のためにデータを正規化する代わりに、挿入時に大文字と小文字を正規化します。Instead of using the system function to normalize data for comparisons, normalize the casing upon insertion. SELECT * FROM c WHERE UPPER(c.name) = 'BOB' のようなクエリが、SELECT * FROM c WHERE c.name = 'BOB' になります。A query like SELECT * FROM c WHERE UPPER(c.name) = 'BOB' becomes SELECT * FROM c WHERE c.name = 'BOB'.
GetCurrentDateTime/GetCurrentTimestamp/GetCurrentTicksGetCurrentDateTime/GetCurrentTimestamp/GetCurrentTicks クエリ実行前に現在の時刻を計算し、その文字列値を WHERE 句で使用します。Calculate the current time before query execution and use that string value in the WHERE clause.
数学関数 (非集計)Mathematical functions (non-aggregates) クエリで値を頻繁に計算する必要がある場合は、JSON ドキュメントのプロパティとして値を格納することを検討します。If you need to compute a value frequently in your query, consider storing the value as a property in your JSON document.

これらのシステム関数では、集計を使用したクエリで使用される場合を除き、インデックスを使用できます。These system functions can use indexes, except when used in queries with aggregates:

システム関数System function 最適化のアイデアIdeas for optimization
空間システム関数Spatial system functions リアルタイムの具体化されたビューにクエリ結果を格納するStore the query result in a real-time materialized view

SELECT 句で使用された場合、非効率的なシステム関数は、クエリでインデックスを使用する方法に影響しません。When used in the SELECT clause, inefficient system functions will not affect how queries can use indexes.

文字列システム関数の実行を改善するImprove string system function execution

インデックスを使用するシステム関数の中には、クエリに ORDER BY 句を追加することによって、クエリの実行を改善できるものもあります。For some system functions that use indexes, you can improve query execution by adding an ORDER BY clause to the query.

具体的には、プロパティのカーディナリティが増加するにつれて RU 料金が増加するすべてのシステム関数は、クエリに ORDER BY を含めることでメリットが得られる可能性があります。More specifically, any system function whose RU charge increases as the cardinality of the property increases may benefit from having ORDER BY in the query. これらのクエリではインデックス スキャンが実行されるため、クエリ結果を並べ替えることにより、クエリの効率を高めることができます。These queries do an index scan, so having the query results sorted can make the query more efficient.

この最適化により、次のシステム関数の実行が向上します。This optimization can improve execution for the following system functions:

  • StartsWith (大文字と小文字を区別しない = true)StartsWith (where case-insensitive = true)
  • StringEquals (大文字と小文字を区別しない = true)StringEquals (where case-insensitive = true)
  • ContainsContains
  • RegexMatchRegexMatch
  • EndsWithEndsWith

たとえば、次のような CONTAINS が含まれる SQL クエリについて考えます。For example, consider the below query with CONTAINS. CONTAINS ではインデックスが使用されますが、関連するインデックスを追加した後でも、次のクエリを実行すると非常に高い RU 料金が発生する場合があります。CONTAINS will use indexes but sometimes, even after adding the relevant index, you may still observe a very high RU charge when running the below query.

元のクエリ:Original query:

SELECT *
FROM c
WHERE CONTAINS(c.town, "Sea")

ORDER BY を追加することで、クエリの実行を改善させることができます。You can improve query execution by adding ORDER BY:

SELECT *
FROM c
WHERE CONTAINS(c.town, "Sea")
ORDER BY c.town

同じ最適化は、フィルターを追加したクエリにも役立ちます。The same optimization can help in queries with additional filters. この場合、ORDER BY 句に等値フィルターを含むプロパティも追加することをお勧めします。In this case, it's best to also add properties with equality filters to the ORDER BY clause.

元のクエリ:Original query:

SELECT *
FROM c
WHERE c.name = "Samer" AND CONTAINS(c.town, "Sea")

ORDER BY と (c.name, c.town) の複合インデックスを追加することで、クエリの実行を改善することができます。You can improve query execution by adding ORDER BY and a composite index for (c.name, c.town):

SELECT *
FROM c
WHERE c.name = "Samer" AND CONTAINS(c.town, "Sea")
ORDER BY c.name, c.town

インデックスを使用する集計クエリについて理解するUnderstand which aggregate queries use the index

ほとんどの場合、Azure Cosmos DB の集計システム関数ではインデックスが使用されます。In most cases, aggregate system functions in Azure Cosmos DB will use the index. ただし、集計クエリのフィルターや追加の句によっては、クエリ エンジンで大量のドキュメントを読み込みことが必要になる場合があります。However, depending on the filters or additional clauses in an aggregate query, the query engine may be required to load a high number of documents. 通常、クエリ エンジンでは、等値および範囲フィルターが最初に適用されます。Typically, the query engine will apply equality and range filters first. これらのフィルターを適用した後で、クエリ エンジンは追加のフィルターを評価し、必要に応じて残りのドキュメントを読み込んで集計を計算できます。After applying these filters, the query engine can evaluate additional filters and resort to loading remaining documents to compute the aggregate, if needed.

たとえば、次の 2 つのサンプル クエリの場合、等値と CONTAINS システム関数フィルターの両方を含むクエリは、通常、CONTAINS システム関数フィルターだけを含むクエリよりも効率的です。For example, given these two sample queries, the query with both an equality and CONTAINS system function filter will generally be more efficient than a query with just a CONTAINS system function filter. これは、より負荷の高い CONTAINS フィルターのためにドキュメントの読み込みが必要になる前に、等値フィルターが最初に適用され、インデックスが使用されるためです。This is because the equality filter is applied first and uses the index before documents need to be loaded for the more expensive CONTAINS filter.

CONTAINS フィルターのみを含むクエリ - RU 料金が高くなる:Query with only CONTAINS filter - higher RU charge:

SELECT COUNT(1)
FROM c
WHERE CONTAINS(c.description, "spinach")

等値フィルターと CONTAINS フィルターを含むクエリ - RU 料金が低くなる:Query with both equality filter and CONTAINS filter - lower RU charge:

SELECT AVG(c._ts)
FROM c
WHERE c.foodGroup = "Sausages and Luncheon Meats" AND CONTAINS(c.description, "spinach")

次に、インデックスを完全には使用しない集計クエリのその他の例を示します。Here are additional examples of aggregate queries that will not fully use the index:

インデックスを使用しないシステム関数を含むクエリQueries with system functions that don't use the index

インデックスを使用するかどうかを確認するには、関連するシステム関数のページを参照する必要があります。You should refer to the relevant system function's page to see if it uses the index.

SELECT MAX(c._ts)
FROM c
WHERE CONTAINS(c.description, "spinach")

ユーザー定義関数 (UDF) を含む集計クエリAggregate queries with user-defined functions(UDF's)

SELECT AVG(c._ts)
FROM c
WHERE udf.MyUDF("Sausages and Luncheon Meats")

ORDER BY を含むクエリQueries with GROUP BY

GROUP BY 句内のプロパティのカーディナリティが増えると、GROUP BY を含むクエリの RU 料金が増加します。The RU charge of queries with GROUP BY will increase as the cardinality of the properties in the GROUP BY clause increases. たとえば、次のクエリでは、一意の説明の数が増えるにつれて、クエリの RU 料金が増加します。In the below query, for example, the RU charge of the query will increase as the number unique descriptions increases.

GROUP BY 句を含む集計関数の RU 料金は、集計関数だけの RU 料金よりも高くなります。The RU charge of an aggregate function with a GROUP BY clause will be higher than the RU charge of an aggregate function alone. この例では、クエリ エンジンは c.foodGroup = "Sausages and Luncheon Meats" フィルターに一致するすべてのドキュメントを読み込む必要があるため、RU 料金が高くなることが予想されます。In this example, the query engine must load every document that matches the c.foodGroup = "Sausages and Luncheon Meats" filter so the RU charge is expected to be high.

SELECT COUNT(1)
FROM c
WHERE c.foodGroup = "Sausages and Luncheon Meats"
GROUP BY c.description

同じ集計クエリを頻繁に実行する予定がある場合は、個々のクエリを実行するのではなく、Azure Cosmos DB の変更フィードを使用して、リアルタイムのマテリアライズドビューを作成する方が効率的です。If you plan to frequently run the same aggregate queries, it may be more efficient to build a real-time materialized view with the Azure Cosmos DB change feed than running individual queries.

フィルターと ORDER BY 句の両方を使用するクエリを最適化するOptimize queries that have both a filter and an ORDER BY clause

通常、フィルターと ORDER BY 句を使用するクエリでは範囲インデックスが使用されますが、複合インデックスから提供できる場合は、効率が向上します。Although queries that have a filter and an ORDER BY clause will normally use a range index, they'll be more efficient if they can be served from a composite index. インデックス作成ポリシーを変更するだけでなく、複合インデックス内のすべてのプロパティを ORDER BY 句に追加する必要があります。In addition to modifying the indexing policy, you should add all properties in the composite index to the ORDER BY clause. このようにクエリを変更すると、複合インデックスが使用されます。This change to the query will ensure that it uses the composite index. 栄養データセットに対してクエリを実行することで、影響を観察できます。You can observe the impact by running a query on the nutrition dataset:

変更元Original

クエリ:Query:

SELECT *
FROM c
WHERE c.foodGroup = "Soups, Sauces, and Gravies"
ORDER BY c._ts ASC

インデックス作成ポリシー:Indexing policy:

{

        "automatic":true,
        "indexingMode":"Consistent",
        "includedPaths":[  
            {  
                "path":"/*"
            }
        ],
        "excludedPaths":[]
}

RU 使用量: 44.28 RURU charge: 44.28 RUs

最適化Optimized

更新されたクエリ (ORDER BY 句の両方のプロパティが含まれます):Updated query (includes both properties in the ORDER BY clause):

SELECT *
FROM c
WHERE c.foodGroup = "Soups, Sauces, and Gravies"
ORDER BY c.foodGroup, c._ts ASC

更新されたインデックス作成ポリシー:Updated indexing policy:

{  
        "automatic":true,
        "indexingMode":"Consistent",
        "includedPaths":[  
            {  
                "path":"/*"
            }
        ],
        "excludedPaths":[],
        "compositeIndexes":[  
            [  
                {  
                    "path":"/foodGroup",
                    "order":"ascending"
        },
                {  
                    "path":"/_ts",
                    "order":"ascending"
                }
            ]
        ]
    }

RU 使用量: 8.86 RURU charge: 8.86 RUs

サブクエリを使用して JOIN 式を最適化するOptimize JOIN expressions by using a subquery

複数値サブクエリは、WHERE 句内のすべてのクロス結合の後ではなく、それぞれの select-many 式の後に述語をプッシュすることによって JOIN 式を最適化できます。Multi-value subqueries can optimize JOIN expressions by pushing predicates after each select-many expression rather than after all cross joins in the WHERE clause.

次のクエリについて考えてみます。Consider this query:

SELECT Count(1) AS Count
FROM c
JOIN t IN c.tags
JOIN n IN c.nutrients
JOIN s IN c.servings
WHERE t.name = 'infant formula' AND (n.nutritionValue > 0
AND n.nutritionValue < 10) AND s.amount > 1

RU 使用量: 167.62 RURU charge: 167.62 RUs

このクエリの場合、インデックスは、infant formula という名前のタグを持ち、nutritionValue が 0 より大きく、amount が 1 より大きいすべてのドキュメントに一致します。For this query, the index will match any document that has a tag with the name infant formula, nutritionValue greater than 0, and amount greater than 1. ここでの JOIN 式は、一致するドキュメントごとに、タグ、栄養素、1 回分の各配列の全項目の外積を、フィルターが適用される前に実行します。The JOIN expression here will perform the cross-product of all items of tags, nutrients, and servings arrays for each matching document before any filter is applied. WHERE 句はその後、<c, t, n, s> タプルごとにフィルター述語を適用します。The WHERE clause will then apply the filter predicate on each <c, t, n, s> tuple.

たとえば、一致するドキュメントで、3 つの配列のそれぞれに 10 個の項目があるとした場合、1 x 10 x 10 x 10 (つまり、1,000) タプルに展開されます。For example, if a matching document has 10 items in each of the three arrays, it will expand to 1 x 10 x 10 x 10 (that is, 1,000) tuples. ここでサブクエリを使用すると、次の式と結合する前に、結合された配列項目をフィルターで除外するために役立ちます。The use of subqueries here can help to filter out joined array items before joining with the next expression.

このクエリは前のものと同等ですが、サブクエリを使用します。This query is equivalent to the preceding one but uses subqueries:

SELECT Count(1) AS Count
FROM c
JOIN (SELECT VALUE t FROM t IN c.tags WHERE t.name = 'infant formula')
JOIN (SELECT VALUE n FROM n IN c.nutrients WHERE n.nutritionValue > 0 AND n.nutritionValue < 10)
JOIN (SELECT VALUE s FROM s IN c.servings WHERE s.amount > 1)

RU 使用量: 22.17 RURU charge: 22.17 RUs

tags 配列の 1 つの項目のみがフィルターに一致し、nutrients 配列と servings 配列の両方に 5 つの項目があるとします。Assume that only one item in the tags array matches the filter and that there are five items for both the nutrients and servings arrays. JOIN 式は、最初のクエリの 1,000 項目とは異なり、1 x 1 x 5 x 5 = 25 項目に展開されます。The JOIN expressions will expand to 1 x 1 x 5 x 5 = 25 items, as opposed to 1,000 items in the first query.

取得したドキュメント数が出力したドキュメント数と等しいクエリQueries where Retrieved Document Count is equal to Output Document Count

[取得したドキュメント数][出力したドキュメント数] とほぼ同じ場合、クエリ エンジンは多くの不要なドキュメントをスキャンする必要がありませんでした。If the Retrieved Document Count is approximately equal to the Output Document Count, the query engine didn't have to scan many unnecessary documents. TOP キーワードを使用するクエリのように、多くのクエリで、 [取得したドキュメント数][出力したドキュメント数] より 1 つ多い可能性があります。For many queries, like those that use the TOP keyword, Retrieved Document Count might exceed Output Document Count by 1. これについて心配する必要はありません。You don't need to be concerned about this.

クロス パーティション クエリを最小化するMinimize cross partition queries

Azure Cosmos DB ではパーティション分割を使用して、要求ユニットとデータ ストレージのニーズの増加に応じて個々のコンテナーをスケーリングします。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'll need to check only the relevant partition's index. この最適化により、クエリが必要とする RU の合計数が減少します。This optimization reduces the total number of RUs that the query requires.

プロビジョニングされた RU 使用量の数が多い (3 万以上) 場合や、大量のデータ (約 100 GB 以上) が格納されている場合は、おそらく、クエリ RU の使用量の大幅な削減を確認するのに十分な大きさなのコンテナーがあります。If you have a large number of provisioned RUs (more than 30,000) or a large amount of data stored (more than approximately 100 GB), you probably have a large enough container to see a significant reduction in query RU charges.

たとえば、foodGroup というパーティション キーを持つコンテナーを作成する場合、次のクエリでは 1 つの物理パーティションのみを確認する必要があります。For example, if you create a container with the partition key foodGroup, the following queries will need to check only a single physical partition:

SELECT *
FROM c
WHERE c.foodGroup = "Soups, Sauces, and Gravies" and c.description = "Mushroom, oyster, raw"

パーティション キーに IN フィルターがあるクエリでは、関連する物理パーティションだけがチェックされ、"ファンアウト" は行われません。Queries that have an IN filter with the partition key will only check the relevant physical partition(s) and will not "fan-out":

SELECT *
FROM c
WHERE c.foodGroup IN("Soups, Sauces, and Gravies", "Vegetables and Vegetable Products") and c.description = "Mushroom, oyster, raw"

パーティション キーに対して範囲フィルターが設定されているか、パーティション キーにフィルターがないクエリは、"ファンアウト" して、すべての物理パーティションのインデックスの結果を確認する必要があります。Queries that have range filters on the partition key, or that don't have any filters on the partition key, will need to "fan-out" and check every physical partition's index for results:

SELECT *
FROM c
WHERE c.description = "Mushroom, oyster, raw"
SELECT *
FROM c
WHERE c.foodGroup > "Soups, Sauces, and Gravies" and c.description = "Mushroom, oyster, raw"

複数のプロパティに対するフィルターがあるクエリを最適化するOptimize queries that have filters on multiple properties

通常、複数のプロパティのフィルターを使用したクエリでは範囲インデックスが使用されますが、複合インデックスから処理できる場合は、効率が向上します。Although queries that have filters on multiple properties will normally use a range index, they'll be more efficient if they can be served from a composite index. 少量のデータの場合、この最適化は大きな影響を与えません。For small amounts of data, this optimization won't have a significant impact. ただし、大量のデータを使用する場合には、便利な場合があります。It could be useful, however, for large amounts of data. 最適化できる非等値フィルターは、複合インデックスごとに最大 1 つです。You can only optimize, at most, one non-equality filter per composite index. クエリに複数の非等値フィルターがある場合は、複合インデックスを使用するクエリを 1 つ選択します。If your query has multiple non-equality filters, pick one of them that will use the composite index. 残りの部分では、範囲インデックスが引き続き使用されます。The rest will continue to use range indexes. 非等値フィルターは、複合インデックス内で最後に定義する必要があります。The non-equality filter must be defined last in the composite index. 複合インデックスについての詳細情報Learn more about composite indexes.

複合インデックスを使用して最適化できるクエリの例をいくつか次に示します。Here are some examples of queries that could be optimized with a composite index:

SELECT *
FROM c
WHERE c.foodGroup = "Vegetables and Vegetable Products" AND c._ts = 1575503264
SELECT *
FROM c
WHERE c.foodGroup = "Vegetables and Vegetable Products" AND c._ts > 1575503264

関連する複合インデックスは次のとおりです。Here's the relevant composite index:

{  
        "automatic":true,
        "indexingMode":"Consistent",
        "includedPaths":[  
            {  
                "path":"/*"
            }
        ],
        "excludedPaths":[],
        "compositeIndexes":[  
            [  
                {  
                    "path":"/foodGroup",
                    "order":"ascending"
                },
                {  
                    "path":"/_ts",
                    "order":"ascending"
                }
            ]
        ]
}

クエリの待機時間を短縮する最適化Optimizations that reduce query latency

多くの場合、クエリの待機時間がまだ長すぎるときは、RU 使用量が許容される可能性があります。In many cases, the RU charge might be acceptable when query latency is still too high. 以下のセクションでは、クエリの待機時間を短縮するためのヒントの概要を説明します。The following sections give an overview of tips for reducing query latency. 同じクエリを同じデータセットに対して複数回実行すると、一般的には毎回同じ RU 使用量が発生します。If you run the same query multiple times on the same dataset, it will typically have the same RU charge each time. ただし、クエリの待機時間はクエリの実行間隔によって異なる場合があります。But query latency might vary between query executions.

近接性の向上Improve proximity

Azure Cosmos DB アカウントとは異なるリージョンから実行されるクエリでは、同じリージョン内で実行された場合よりも待機時間が長くなります。Queries that are run from a different region than the Azure Cosmos DB account will have higher latency than if they were run inside the same region. たとえば、デスクトップ コンピューターでコードを実行していた場合、クエリが Azure Cosmos DB と同じ Azure リージョン内の仮想マシンからのものである場合よりも、待機時間は数十ミリ秒または数百ミリ秒 (またはそれ以上) 分長くなることが予想されます。For example, if you're running code on your desktop computer, you should expect latency to be tens or hundreds of milliseconds higher (or more) than if the query came from a virtual machine within the same Azure region as Azure Cosmos DB. データをアプリの近くに配置できるように、Azure Cosmos DB にデータをグローバルに分散することは簡単です。It's simple to globally distribute data in Azure Cosmos DB to ensure you can bring your data closer to your app.

プロビジョニングされたスループットの増加Increase provisioned throughput

Azure Cosmos DB では、プロビジョニングされたスループットは要求ユニット (RU) で測定されます。In Azure Cosmos DB, your provisioned throughput is measured in Request Units (RUs). 5 RU のスループットを使用するクエリがあると仮定します。Imagine you have a query that consumes 5 RUs of throughput. たとえば、1,000 RU をプロビジョニングする場合、そのクエリは 1 秒あたり 200 回実行できます。For example, if you provision 1,000 RUs, you would be able to run that query 200 times per second. スループットが十分でないときにクエリを実行しようとすると、Azure Cosmos DB によって HTTP 429 エラーが返されます。If you tried to run the query when there wasn't enough throughput available, Azure Cosmos DB would return an HTTP 429 error. 現在の Core (SQL) API SDK では、短時間待機した後に、このクエリを自動的に再試行します。Any of the current Core (SQL) API SDKs will automatically retry this query after waiting for a short time. スロットルされた要求にはさらに時間がかかるため、プロビジョニングされたスループットを増やすとクエリの待機時間が改善します。Throttled requests take longer, so increasing provisioned throughput can improve query latency. Azure portal の [メトリック] ブレードで、調整された要求の合計数を確認できます。You can observe the total number of throttled requests on the Metrics blade of the Azure portal.

MaxConcurrency の増加Increase MaxConcurrency

並列クエリは、複数のパーティションに並列にクエリを実行することによって機能します。Parallel queries work by querying multiple partitions in parallel. ただし、個々のパーティション分割されたコレクションからのデータは、クエリごとに順番に取得されます。But data from an individual partitioned collection is fetched serially with respect to the query. そのため、MaxConcurrency をパーティションの数に設定すると、その他のすべてのシステムの条件が変わらなければ、クエリのパフォーマンスを最大にできる可能性が最大になります。So, if you set MaxConcurrency to the number of partitions, you have the best chance of achieving the most performant query, provided all other system conditions remain the same. パーティションの数がわからない場合は、MaxConcurrency (または古いバージョンの SDK では MaxDegreesOfParallelism) を高い値に設定できます。If you don't know the number of partitions, you can set MaxConcurrency (or MaxDegreesOfParallelism in older SDK versions) to a high number. システムにより、最大の並列処理の次数として最小値 (パーティションの数、ユーザー指定の入力) が選択されます。The system will choose the minimum (number of partitions, user provided input) as the maximum degree of parallelism.

MaxBufferedItemCount の増加Increase MaxBufferedItemCount

クエリは、結果の現在のバッチがクライアントによって処理されている間に結果をプリフェッチするように設計されています。Queries are designed to pre-fetch results while the current batch of results is being processed by the client. プリフェッチは、クエリの全体的な遅延の削減に役立ちます。Pre-fetching helps to improve the overall latency of a query. MaxBufferedItemCount を設定すると、プリフェッチされる結果の数が制限されます。Setting MaxBufferedItemCount limits the number of pre-fetched results. この値を、返される結果の予期される数 (またはそれ以上の数) に設定すると、クエリに対するプリフェッチの効果が最大になります。If you set this value to the expected number of results returned (or a higher number), the query can get the most benefit from pre-fetching. この値を -1 に設定すると、バッファーに格納される項目の数はシステムによって自動的に決定されます。If you set this value to -1, the system will automatically determine the number of items to buffer.

次のステップNext steps

クエリあたりの RU 数を測定する方法や、実行の統計を取得してクエリの調整を行う方法などについては、次の記事を参照してください。See the following articles for information on how to measure RUs per query, get execution statistics to tune your queries, and more: