Azure Cosmos DB のクエリのパフォーマンスをトラブルシューティングするTroubleshoot query performance for Azure Cosmos DB

この記事では、Azure Cosmos DB の SQL クエリに関する問題を特定、診断、およびトラブルシューティングする方法について説明します。This article covers how to identify, diagnose, and troubleshoot Azure Cosmos DB SQL query issues. Azure Cosmos DB のクエリのパフォーマンスを最適化するには、次のトラブルシューティング手順に従います。In order to achieve optimal performance for Azure Cosmos DB queries, follow the troubleshooting steps below.

クライアントを同じ Azure リージョンに併置するCollocate clients in same Azure region

最短の待機時間は、プロビジョニングされた Azure Cosmos DB エンドポイントと同じ Azure リージョン内に呼び出し元アプリケーションを配置することによって実現されます。The lowest possible latency is achieved by ensuring the calling application is located within the same Azure region as the provisioned Azure Cosmos DB endpoint. 利用可能なリージョンの一覧については、記事「Azure リージョン」をご覧ください。For a list of available regions, see Azure Regions article.

整合性レベルを確認するCheck consistency level

整合性レベルは、パフォーマンスと料金に影響する可能性があります。Consistency level can impact performance and charges. 整合性レベルが特定のシナリオに適していることを確認します。Make sure your consistency level is appropriate for the given scenario. 詳細については、整合性レベルの選択に関する記事をご覧ください。For more details see Choosing Consistency Level.

Sql クエリをストレージ アカウントに記録するLog Sql query in storage account

診断ログを使用した Sql API クエリ ログを使用すると、難読化されたクエリを任意のストレージ アカウントに記録できます。Sql API query logs through diagnostic logs allows to log the obfuscated query in a storage account of your choice. これにより、診断ログを確認し、より多くの RU を使用するクエリの検索を実行して、アクティビティ ID を使用して QueryRuntimeStatistics で照合することができます。This allow you to look at the Diagnostic logs and find query using more RUs and use the activity id to match in the QueryRuntimeStatistics.

ログ クエリ メトリックLog query metrics

低速または高コストのクエリをトラブルシューティングするために、QueryMetrics を使用します。Use QueryMetrics to troubleshoot slow or expensive queries.

  • QueryMetrics を応答に含めるために FeedOptions.PopulateQueryMetrics = true を設定します。Set FeedOptions.PopulateQueryMetrics = true to have QueryMetrics in the response.

  • QueryMetrics クラスには、オーバーロードされた .ToString() 関数があります。これを呼び出すと、QueryMetrics の文字列表現を取得できます。QueryMetrics class has an overloaded .ToString() function that can be invoked to get the string representation of QueryMetrics.

  • メトリックを使用すると、特に次の分析情報を得ることができます。The metrics can be utilized to derive the following insights, among others:

    • クエリ パイプラインの特定のコンポーネントの完了に異常に長い時間がかかっているかどうか (数百ミリ秒以上)。Whether any specific component of the query pipeline took abnormally long to complete (in order of hundreds of milliseconds or more).

      • TotalExecutionTime を確認します。Look at TotalExecutionTime.
      • クエリの TotalExecutionTime がエンドツーエンドの実行時間よりも短い場合、クライアント側またはネットワークで時間がかかっています。If the TotalExecutionTime of the query is less than the end to end execution time, then the time is being spent in client side or network. クライアントと Azure リージョンが併置されていることを再度確認します。Double check that the client and Azure region are collocated.
    • 分析されたドキュメントに誤検出があるかどうか (出力ドキュメント数が、取得されたドキュメント数よりもはるかに少ない場合)。Whether there were false positives in the documents analyzed (if Output Document Count is much less than Retrieved Document Count).

      • Index Utilization を確認します。Look at Index Utilization.
      • Index Utilization = (返されたドキュメントの数/読み込まれたドキュメントの数)Index Utilization = (Number of returned documents / Number of loaded documents)
      • 返されたドキュメントの数が読み込まれた数よりもはるかに少ない場合、誤検出が分析されます。If the number of returned documents is much less than the number loaded, then false positives are being analyzed.
      • フィルターを絞り込むことで、取得するドキュメントの数を制限します。Limit the number of documents being retrieved with narrower filters.
    • 個々のラウンドトリップがどのように処理されたか (QueryMetrics の文字列表現から Partition Execution Timeline を確認します)。How individual round-trips fared (see the Partition Execution Timeline from the string representation of QueryMetrics).

    • クエリで高コストの要求使用量が発生したかどうか。Whether the query consumed high request charge.

詳細については、SQL クエリの実行メトリックの取得方法に関する記事をご覧ください。For more details see How to get SQL query execution metrics article.

クエリのフィード オプション パラメーターを調整するTune Query Feed Options Parameters

クエリのパフォーマンスは、要求のフィード オプション パラメーターを使用して調整できます。Query performance can be tuned via the request's Feed Options Parameters. 次のオプションを設定してみてください。Try setting the below options:

  • 最初に MaxDegreeOfParallelism を -1 に設定し、その後、異なる値でパフォーマンスを比較します。Set MaxDegreeOfParallelism to -1 first and then compare performance across different values.
  • 最初に MaxBufferedItemCount を -1 に設定し、その後、異なる値でパフォーマンスを比較します。Set MaxBufferedItemCount to -1 first and then compare performance across different values.
  • MaxItemCount を -1 に設定します。Set MaxItemCount to -1.

異なる値でパフォーマンスを比較するときは、2、4、8、16 などの値を試してください。When comparing performance of different values, try values such as 2, 4, 8, 16, and others.

継続からすべての結果を読み取るRead all results from continuations

すべての結果を取得していないと考えられる場合は、継続を完全にドレインしてください。If you think you are not getting all the results, make sure to drain the continuation fully. つまり、継続トークンによって多くのドキュメントが生成されている間、結果の読み取りを続けます。In other words, keep reading results while the continuation token has more documents to yield.

完全なドレインは、次のいずれかのパターンで実現できます。Fully draining can be achieved with either of the following patterns:

  • 継続が空ではない間、結果の処理を続けます。Continue processing results while continuation is not empty.

  • クエリによって多くの結果が生成される間、処理を続けます。Continue processing while query has more results.

    // using AsDocumentQuery you get access to whether or not the query HasMoreResults
    // If it does, just call ExecuteNextAsync until there are no more results
    // No need to supply a continuation token here as the server keeps track of progress
    var query = client.CreateDocumentQuery<Family>(collectionLink, options).AsDocumentQuery();
    while (query.HasMoreResults)
    {
        foreach (Family family in await query.ExecuteNextAsync())
        {
            families.Add(family);
        }
    }
    

インデックスを使用するシステム関数を選択するChoose system functions that utilize index

式を文字列値の範囲に変換できる場合、インデックスを使用できます。そうでない場合は使用できません。If the expression can be translated into a range of string values, then it can utilize the index; otherwise, it cannot.

インデックスを使用できる文字列関数の一覧を次に示します。Here is the list of string functions that can utilize the index:

  • STARTSWITH(str_expr, str_expr)STARTSWITH(str_expr, str_expr)

  • LEFT(str_expr, num_expr) = str_exprLEFT(str_expr, num_expr) = str_expr

  • SUBSTRING(str_expr, num_expr, num_expr) = str_expr, but only if first num_expr is 0SUBSTRING(str_expr, num_expr, num_expr) = str_expr, but only if first num_expr is 0

    次にクエリの例をいくつか示します。Here are few query examples:

    
    -- If there is a range index on r.name, STARTSWITH will utilize the index while ENDSWITH won't 
    SELECT * 
    FROM c 
    WHERE STARTSWITH(c.name, 'J') AND ENDSWITH(c.name, 'n')
    
    
    
    -- LEFT will utilize the index while RIGHT won't 
    SELECT * 
    FROM c 
    WHERE LEFT(c.name, 2) = 'Jo' AND RIGHT(c.name, 2) = 'hn'
    
    
  • インデックスによって処理されないフィルター (または WHERE 句) でシステム関数は使用しないでください。Avoid system functions in the filter (or the WHERE clause) that are not served by the index. このようなシステム関数の例として、Contains、Upper、Lower などがあります。Some examples of such system functions include Contains, Upper, Lower.

  • 可能な場合は、パーティション キーでフィルターを使用するクエリを記述します。When possible, write queries to use a filter on partition key.

  • クエリのパフォーマンスを向上させるために、フィルターで UPPER/LOWER を呼び出さないようにします。To achieve performant queries avoid calling UPPER/LOWER in the filter. 代わりに、挿入時に値の大文字と小文字を正規化します。Instead, normalize casing of values upon insertion. それぞれの値について、必要な大文字と小文字を使用した値を挿入するか、元の値と、必要な大文字と小文字を使用した値の両方を挿入します。For each of the values insert the value with desired casing, or insert both the original value and the value with the desired casing.

    例:For example:

    
    SELECT * FROM c WHERE UPPER(c.name) = "JOE"
    
    

    この場合、すべて大文字の "JOE" を格納するか、元の値である "Joe" と "JOE" の両方を格納します。For this case, store "JOE" capitalized or store both "Joe" the original value and "JOE".

    JSON データの大文字と小文字が正規化されている場合、クエリは次のようになります。If the JSON data casing is normalized the query becomes:

    
    SELECT * FROM c WHERE c.name = "JOE"
    
    

    2 番目のクエリではパフォーマンスがより向上します。これは、"JOE" と値を比較するために、各値に対して変換を実行する必要がないためです。The second query will be more performant as it does not require performing transformations on each of the values in order to compare the values to "JOE".

システム関数の詳細については、記事「システム関数」をご覧ください。For more system function details see System Functions article.

インデックス作成ポリシーを確認するCheck Indexing policy

現在のインデックス作成ポリシーが最適であるか確認するには、次のようにします。To verify that the current Indexing Policy is optimal:

  • 読み取りを高速にするために、クエリで使用されるすべての JSON パスがインデックス作成ポリシーに含まれていることを確認します。Ensure all JSON paths used in queries are included in the indexing policy for faster reads.
  • 書き込みのパフォーマンスを向上させるために、クエリで使用されないパスは除外します。Exclude paths not used in queries for more performant writes.

詳細については、記事「インデックス作成ポリシーを管理する方法」をご覧ください。For more details see How To Manage Indexing Policy article.

空間データ:ポイントの順序を確認するSpatial data: Check ordering of points

Polygon 内のポイントは、反時計回りに指定する必要があります。Points within a Polygon must be specified in counter-clockwise order. 時計回りに指定された Polygon は、その中の領域を逆にしたものを表します。A Polygon specified in clockwise order represents the inverse of the region within it.

JOIN 式を最適化するOptimize JOIN expressions

JOIN 式は、大規模なクロス積に展開できます。JOIN expressions can expand into large cross products. 可能な場合は、より絞り込んだフィルターを使用して、より小さい検索領域に対してクエリを実行します。When possible, query against a smaller search space via a more narrow filter.

複数値サブクエリは、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. 詳細な例については、記事「JOIN 式を最適化する」をご覧ください。For a detailed example see Optimize Join Expressions article.

ORDER BY 式を最適化するOptimize ORDER BY expressions

フィールドがスパースである場合、またはインデックス ポリシーに含まれていない場合、ORDER BY クエリのパフォーマンスが低下する可能性があります。ORDER BY query performance may suffer if the fields are sparse or not included in the index policy.

  • 時間などのスパース フィールドでは、フィルターを使用して検索領域をできるだけ小さくします。For sparse fields such as time, decrease the search space as much as possible with filters.
  • 単一のプロパティ ORDER BY については、インデックス ポリシーにプロパティを含めます。For single property ORDER BY, include property in index policy.
  • 複数のプロパティ ORDER BY の式については、並べ替えられるフィールドに対して複合インデックスを定義します。For multiple property ORDER BY expressions, define a composite index on fields being sorted.

多数の大規模ドキュメントの読み込みと処理Many large documents being loaded and processed

クエリに必要な時間と RU は、応答のサイズだけでなく、クエリ処理パイプラインによって実行される処理にも依存します。The time and RUs that are required by a query are not only dependent on the size of the response, they are also dependent on the work that is done by the query processing pipeline. 時間と RU は、クエリ処理パイプライン全体によって実行される処理量に比例して増加します。Time and RUs increase proportionally with the amount of work done by the entire query processing pipeline. 大規模なドキュメントの場合、より多くの処理が実行されるため、大規模なドキュメントを読み込んで処理するには、より多くの時間と RU が必要になります。More work is performed for large documents, thus more time and RUs are required to load and process large documents.

プロビジョニングされているスループットが低いLow provisioned throughput

プロビジョニングされたスループットでワークロードを処理できることを確認します。Ensure provisioned throughput can handle workload. 影響を受けるコレクションの RU 予算を増やします。Increase RU budget for impacted collections.

最新の SDK バージョンにアップグレードするTry upgrading to the latest SDK version

最新の SDK を確認するには、SDK のダウンロードとリリース ノートに関する記事をご覧ください。To determine the latest SDK see SDK Download and release notes article.

次の手順Next steps

次のドキュメントを参照して、クエリあたりの RU 数を測定する方法を確認し、実行の統計を取得してクエリの調整などを行います。Refer to documents below on how to measure RUs per query, get execution statistics to tune your queries, and more: