2015-08-29 43 views
15

我目前正面臨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越來越是360ms和1200ms之間返回31個對象。對我而言,那是慢。如果沒有自定義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 
+0

您是否曾嘗試在與您的DocumentDB實例相同的數據中心中運行代碼?我對我的系統在快速互聯網連接(即使是一次操作最少250ms)上運行操作感到非常失望,但是當我運行在同一個數據中心時,延遲低於10ms。如果您不想將實驗推送到數據中心,請嘗試使用10倍數據量的查詢。我懷疑你只會看到稍微增加的數字。如果是這樣,那會給你證據表明它是從數據中心外部調用它的延遲。 –

+0

我確實認爲有一種情況是,從延遲角度來看,穿越數據中心邊界太昂貴。我的網絡連接上的ping時間只有50-70ms。即使加倍,也不能解釋最小250ms的延遲。 –

+0

我可以這麼說:從同一個數據中心的SQL服務器(Azure)檢索31行比這更快_much_。即使行數比從DocumentDB中檢索到的對象數據更多。 –

回答

15

更新,以反映最新的服務變化(2017年1月22日): DocumentDB保證P99讀取延遲< 10毫秒和p99在數據庫端使用SLA寫入延遲時間爲012毫秒。下面仍然提示適用於實現低延遲讀取使用的SDK **

更新,以反映最新的服務變化(2016年6月14日):沒有必要緩存自鏈接通過用戶使用時的路由定義的ID。另外還增加了一些技巧**

讀取通常需要< DocumentDB存儲分區本身1毫秒;瓶頸通常是應用程序和數據庫之間的網絡延遲。因此,最好讓應用程序與數據庫在同一個數據中心中運行。

這裏是SDK使用的一般提示:

提示#1:使用單DocumentDB客戶端應用程序

注意的壽命,每個DocumentClient實例是線程安全的,並且執行效率在直接模式下運行時的連接管理和地址緩存。爲了通過DocumentClient實現高效的連接管理和更好的性能,建議在應用程序的整個生命週期中,爲每個AppDomain使用一個DocumentClient實例。

提示#2:高速緩存文件和收集SelfLinks對於較低的讀延遲

在天青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 MB的塊形式返回,無論哪個限制首先被觸發。

爲了減少檢索所有適用結果所需的網絡往返次數,可以使用x-ms-max-item-count請求標頭將頁面大小增加到1000.如果需要只顯示一些結果,例如,如果您的用戶界面或應用程序API一次只返回十個結果,則還可以將頁面大小減小到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爲查找
  • 配置DocumentDB客戶端(使用ConnectionPolicy)以通過網關使用直接連接
  • 在與您的數據庫相同的Azure區域中配置客戶端
  • Call Op enAsync(),以防止更高的首次呼叫延遲
  • 您可以通過調用toString()的可查詢看到通過線路發送

更多的性能提示SQL查詢調試LINQ查詢,看看這個blog post

+1

爲什麼尖端#2劃掉了? – Andy