web-dev-qa-db-ja.com

Azure DocumentDBのパフォーマンスが遅い

現在、Azure DocumentDBからの非常に遅い応答時間に直面しています(初めて試してみました)。

コレクションには31のオブジェクトがあり、これをフェッチして呼び出し元に返します。私が使用しているコードはこれです:

public async Task<List<dynamic>> Get(string collectionName = null)
{
    // Lookup from Dictionary, takes literally no time
    var collection = await GetCollectionAsync(collectionName);

    var sw = Stopwatch.StartNew();

    var query = await
        _client.CreateDocumentQuery(collection.DocumentsLink, 
            new FeedOptions { MaxItemCount = 1000 })
            .AsDocumentQuery()
            .ExecuteNextAsync();

    Trace.WriteLine($"Get documents: {sw.ElapsedMilliseconds} ms");

    return query.ToList();
}

クライアントをインスタンス化するには、次のコードを使用しています。

_client = new DocumentClient(new Uri(endpoint), authKey, new ConnectionPolicy
{
    ConnectionMode = ConnectionMode.Direct,
    ConnectionProtocol = Protocol.Tcp
});

Stopwatchから取得する応答時間は、31オブジェクトを返すために360ミリ秒から1200ミリ秒です。私にとって、それはかなり遅いです。カスタムConnectionPolicyがない場合、平均応答時間は約950msです。

ここで何か悪いことをしていますか?これらのリクエストをどうにかしてスピードアップすることは可能ですか?

トレースからの出力で、ストップウォッチの経過時間を出力します。

Get documents: 1984 ms
Get documents: 1252 ms
Get documents: 1246 ms
Get documents: 359 ms
Get documents: 356 ms
Get documents: 356 ms
Get documents: 351 ms
Get documents: 1248 ms
Get documents: 1314 ms
Get documents: 1250 ms
19
Andre Andersen

最新のサービス変更を反映するように更新(2017年1月22日):DocumentDBは、SLAがオンの状態でp99読み取りレイテンシ<10ミリ秒とp99書き込みレイテンシ<15ミリ秒を保証しますデータベース側。以下のヒントは、SDKを使用して低レイテンシの読み取りを実現するためにも適用されます**

最新のサービス変更を反映するように更新(2016年6月14日):ユーザー定義のIDを介したルーティングを使用する場合、セルフリンクをキャッシュする必要はありません。また、いくつかのヒントを追加しました。**

通常、DocumentDBストレージパーティション自体の読み取りには1ミリ秒未満かかります。多くの場合、ボトルネックはアプリケーションとデータベース間のネットワーク遅延です。したがって、データベースと同じデータセンターでアプリケーションを実行するのが最適です。

SDKの使用に関するいくつかの一般的なヒントを次に示します。

ヒント#1:アプリケーションの存続期間中、シングルトンDocumentDBクライアントを使用します

各DocumentClientインスタンスはスレッドセーフであり、ダイレクトモードで動作しているときに効率的な接続管理とアドレスキャッシングを実行することに注意してください。 DocumentClientによる効率的な接続管理とより良いパフォーマンスを可能にするために、アプリケーションの存続期間中、AppDomainごとにDocumentClientの単一インスタンスを使用することをお勧めします。

ヒント#2:ドキュメントとコレクションのSelfLinkをキャッシュして読み取りレイテンシを低くする

Azure DocumentDBでは、各ドキュメントにシステム生成のselfLinkがあります。これらのselfLinkは、ドキュメントの存続期間中、一意で不変であることが保証されています。 selfLinkを使用して単一のドキュメントを読み取ることは、単一のドキュメントを取得する最も効率的な方法です。 selfLinkは不変であるため、読み取りパフォーマンスを最適化するには、可能な限りselfLinkをキャッシュする必要があります。

Document document = await client.ReadDocumentAsync("/dbs/1234/colls/1234354/docs/2332435465");

そうは言っても、アプリケーションが読み取りシナリオでドキュメントのselfLinkを操作できるとは限りません。この場合、ドキュメントを取得する次の最も効率的な方法は、ドキュメントのユーザー指定のIdプロパティによるクエリです。例えば:

IDocumentQuery<Document> query = (from doc in client.CreateDocumentQuery(colSelfLink) where doc.Id == "myId" select document).AsDocumentQuery(); 
            Document myDocument = null;
            while (query.HasMoreResults)
            {
                FeedResponse<Document> res = await query.ExecuteNextAsync<Document>();
                if (res.Count != 0) {
                    myDocument = res.Single();
                    break;
                }
           }

ヒント#3:クエリのページサイズを調整する/フィードを読み取ってパフォーマンスを向上させる

読み取りフィード機能(つまり、ReadDocumentFeedAsync)を使用してドキュメントの一括読み取りを実行するとき、またはDocumentDB SQLクエリを発行するとき、結果セットが大きすぎる場合、結果はセグメント化された方法で返されます。デフォルトでは、結果は100アイテムまたは1 M​​Bのチャンクで返されます。

該当するすべての結果を取得するために必要なネットワークラウンドトリップの数を減らすために、x-ms-max-item-countリクエストヘッダーを使用してページサイズを最大1000に増やすことができます。少数のみを表示する必要がある場合結果、たとえば、ユーザーインターフェイスまたはアプリケーションAPIが一度に10件の結果しか返さない場合は、ページサイズを10に減らして、読み取りとクエリに消費されるスループットを減らすこともできます。

使用可能なDocumentDB SDKを使用してページサイズを設定することもできます。例えば:

IQueryable<dynamic> authorResults =
client.CreateDocumentQuery(documentCollection.SelfLink, "SELECT p.Author FROM Pages p WHERE p.Title = 'About Seattle'", new FeedOptions { MaxItemCount = 1000 });

さらにいくつかのヒント(2016年6月14日):

  • IDによる検索にポイント読み取り(クエリドキュメントではなくドキュメントを読み取るなど)を使用する
  • ゲートウェイ経由の直接接続を使用するように(ConnectionPolicyを使用して)DocumentDBクライアントを構成する
  • データベースと同じAzureリージョンにクライアントを配置する
  • OpenAsync()を呼び出して、最初の呼び出しの待ち時間が長くなるのを防ぎます
  • クエリでToString()を呼び出してLINQクエリをデバッグし、ネットワーク経由で送信されたSQLクエリを確認できます。

パフォーマンスに関するその他のヒントについては、こちら ブログ投稿 をご覧ください。

20
Andrew Liu