2017-05-23 37 views
3

我有一個場景,我存儲了大量的第三方數據以供業務用戶進行即席分析。大多數針對數據的查詢都會很複雜,使用多個自連接,投影和範圍。DocumentDB PartitionKey和性能

當談到選擇一個PartitionKey用於天青DocumentDB,我看到有人建議使用邏輯分離,如TenantId,設備ID等

鑑於DocumentDB的並行特性,但是,我很好奇它將如何處理基於某種GUID或大整數的PartitionKey,以便在大讀取期間,它將被高度並列化。

考慮到這一點,我設計了一個試驗具有兩個集合:

  1. test-col-1
    • PartitionKey是TenantId用大致100可能值
  2. test-col-2
    • PartitionKey是由遵循模式「AB1234568」的第三方分配的唯一值。保證在第三方的全球獨一無二。

這兩個集合都設置爲100,000 RU。

在我的實驗中,我用大約2,000個文檔加載了兩個集合。每個文檔的大小約爲20 KB,並且非常規範化。每個文檔就是命令,它包含多個作業,每個包含用戶,價格等

例子查詢:

SELECT 
orders.Attributes.OrderNumber, 
orders.Attributes.OpenedStamp, 
jobs.SubOrderNumber, 
jobs.LaborTotal.Amount As LaborTotal, 
jobs.LaborActualHours As LaborHours, 
jobs.PartsTotal.Amount As PartsTotal, 
jobs.JobNumber, 
jobs.Tech.Number As TechNumber, 
orders.Attributes.OrderPerson.Number As OrderPersonNumber, 
jobs.Status 
FROM orders 
JOIN jobs IN orders.Attributes.Jobs 
JOIN tech IN jobs.Techs 
WHERE orders.TenantId = @TentantId 
    AND orders.Attributes.Type = 1 
    AND orders.Attributes.Status IN (4, 5)"; 

在我的測試中我調整了以下設置:

  1. 默認ConnectionPolicy
  2. Best practices ConnectionPolicy
    • ConnectionMode.DirectProtocol.Tcp
  3. 各種MaxDegreeOfParallelism
  4. 各種MaxBufferedItemCount

收集具有GUID PartitionKey被查詢與EnableCrossPartitionQuery = true。我正在使用C#和.NET SDK v1.14.0。

在我使用默認設置初始測試中,我發現,查詢收集與TentantId作爲PartitionKey是更快,它以平均3,765毫秒相比4,680毫秒的GUID鍵控集合。

當我設置ConnectionPolicyDirectTCP,我發現TenantID集合查詢時間由近1000毫秒減少到平均2865毫秒而GUID集增加了約800毫秒,平均5492毫秒

當我開始玩MaxDegreeOfParellelismMaxBufferedItemCount時,事情開始變得有趣。 TentantID集合查詢時間通常不受影響,因爲查詢不是交叉收集,但是GUID集合顯着加快,達到的值與450 msMaxDegreeOfParellelism = 2000,MaxBufferedItemCount = 2000)一樣快。


考慮到這些意見,爲什麼你會不想讓PartitionKey儘可能廣泛的值儘可能

回答

2

當我開始玩弄MaxDegreeOfParellelism和MaxBufferedItemCount時,事情開始變得有趣。 TentantID收集查詢時間通常不受影響,因爲查詢不是交叉收集,但是GUID收集速度顯着提高,達到450毫秒(MaxDegreeOfParellelism = 2000,MaxBufferedItemCount = 2000)的值。

MaxDegreeOfParallelism可以設置由ParallelOptions實例啓用的最大併發任務數。據我所知,這是一個客戶端並行性,它會花費您在您的網站上擁有的CPU /內存資源。

鑑於這些意見,爲什麼不想讓PartitionKey儘可能廣泛的值?

對於寫入操作,我們可以跨越分區鍵進行縮放,以便使用已設置的整個分區鍵。而對於讀取操作,我們需要儘量減少跨分區查找以獲得更低的延遲。

而且,提到這個正式文件:

分區鍵的選擇是,你必須做在設計時的一項重要決策。 您必須選擇一個屬性名稱,其值範圍很廣並且具有訪問模式。

最佳做法是讓具有許多不同值(至少爲100s-1000s)的分區鍵

要實現容器的完整吞吐量,您必須選擇一個分區鍵,以便您在一些不同的分區鍵值之間平均分配請求。

欲瞭解更多詳情,你可以參考How to partition and scale in Azure Cosmos DB和這個頻道9教程約Azure DocumentDB Elastic Scale - Partitioning