Azure Cosmos DB 會使用資料分割來調整資料庫中的容器以符合您應用程式效能需求。 系統會將容器中的項目分割為不同子集,稱為邏輯分割區。 邏輯分割區是根據與容器中每個項目相關聯的分割區索引鍵值而建立。 邏輯分割區中的所有項目都有相同的分割區索引鍵值。
例如,容器會保存項目。 每個項目針對 UserID 屬性都會有唯一的值。 如果 UserID 用來作為容器中項目的分割區索引鍵,而且有 1,000 個唯一的 UserID 值,則系統會為該容器建立 1,000 個邏輯分割區。
容器中的每個項目都有一個分割區索引鍵,用來決定其邏輯分割區和該分割區中唯一的項目識別碼。 透過合併分割區索引鍵和「項目識別碼」,會建立項目的「索引」,其能唯一識別該項目。 選擇分割區索引鍵是影響應用程式效能的重要決策。
本文說明邏輯和實體分割區之間的關係、討論分割的最佳作法,並深入探索 Azure Cosmos DB 中水平縮放的運作方式。 您並不需要瞭解這些內部詳細資料來選取分割區索引鍵,但本文必須涵蓋這些內容才能清楚說明 Azure Cosmos DB 的運作方式。
邏輯分割區
邏輯分割區是一組共用相同分割區索引鍵的項目。 例如,在包含食物營養相關資料的容器中,所有項目都會包含一個 foodGroup 屬性。 使用 foodGroup 作為容器的分割區索引鍵。 針對 foodGroup 具有特定值的項目群組,例如 Beef Products、Baked Products 和 Sausages and Luncheon Meats,會形成不同的邏輯分割區。
邏輯分割區也會定義資料庫交易的範圍。 您可以使用含有快照集隔離的交易來更新邏輯分割區內的項目。 將新項目新增至容器時,系統會以透明方式建立新的邏輯分割區。 刪除底層資料時,您不需要擔心會刪除邏輯分割區。
容器中的邏輯分割區數目沒有任何限制。 每個邏輯分割區最多可以儲存 20 GB 的資料。 有效的分割區索引鍵有各式各樣的可能值。 例如,在所有項目都包含 foodGroup 屬性的容器中,Beef Products 邏輯分割區內的資料最多可成長至 20 GB。
選取具有各種可能值的分割區索引鍵可確保容器能夠調整規模。
使用 Azure 監視器警示來監視邏輯分割區的大小是否已接近 20 GB。
實體分割區
容器調整是在實體分割區之間分配資料和輸送量。 就內部而言,會有一或多個邏輯分割區對應至單一實體分割區。 通常較小的容器具有許多邏輯分割區,但其只需要單一實體分割區。 與邏輯分割區不同,實體分割區是內部系統實作,全部由 Azure Cosmos DB 管理。
容器中的實體分割區數量取決於下列特性:
所佈建的輸送量數目 (每個個別的實體分割區可以提供每秒最多 10,000 個要求單位的輸送量)。 實體分割區每秒 10,000 RU 的限制,表示邏輯分割區也會有每秒 10,000 RU 的限制,因為每個邏輯分割區只對應到一個實體分割區。
總資料儲存體 (每個個別的實體分割區最多可以儲 50 GB 的資料)。
附註
實體分割區是內部系統實作,全部由 Azure Cosmos DB 管理。 開發解決方案時,請勿專注於實體分割區,因為您無法加以控制。 相反地,請將焦點放在分割區索引鍵上。 選擇將輸送量耗用量平均分配給邏輯分割區的分割區索引鍵,可確保各實體分割區間的輸送量耗用量保持平衡。
容器中的實體分割區總數沒有任何限制。 當您佈建的輸送量或資料大小增加時,Azure Cosmos DB 將會分割現有的實體分割區,以自動建立新的實體分割區。 實體分割區分割不會影響應用程式的可用性。 分割實體分割區之後,單一邏輯分割區內的所有資料仍會儲存在相同的實體分割區上。 實體分割區分割只會在邏輯分割區與實體分割區之間建立新對應。
為容器佈建的輸送量會平均分配給各實體分割區。 未平均分散要求的分割區索引鍵設計,可能會導致系統將太多要求導向一小部分的分割區,使其變成「經常性存取」。經常性存取分割區會造成佈建的輸送量使用效率不佳,導致速率限制和成本增加。
例如,請考慮指定為分割區金鑰的路徑 /foodGroup 包含在內的容器。 容器可以有任意數目的實體分割區,但在此範例中,我們假設它有三個。 單一實體分割區可以包含多個分割區金鑰。 例如,最大的實體分割區可能包含前三個最大大小邏輯分割區:Beef Products、Vegetable and Vegetable Products 和 Soups, Sauces, and Gravies。
如果您指派 18,000 每秒要求單位 (RU/s) 的輸送量,則這三個實體分割區個別都可以利用總佈建輸送量的三分之一。 在選取的實體分割區內,邏輯分割區索引鍵 Beef Products、Vegetable and Vegetable Products 和 Soups, Sauces, and Gravies 合起來可以利用實體分割區佈建的 6,000 RU/S。 因為佈建的輸送量會在容器的實體分割區之間平均分配,所以必須選擇能平均分配輸送量耗用量的分割區索引鍵。 如需詳細資訊,請參閱選擇正確的邏輯分割區金鑰。
管理邏輯分割區
Azure Cosmos DB 會自動管理在實體分割區上的邏輯分割區放置,以便符合容器的可擴縮性和效能需求。 當應用程式的輸送量和儲存體需求增加時,Azure Cosmos DB 就會移動邏輯分割區,以便將負載分散到更多實體分割區上。 深入了解實體分割區。
Azure Cosmos DB 會使用雜湊型資料分割,將邏輯分割區分散到實體分割區上。 Azure Cosmos DB 會對項目的分割區索引鍵值進行雜湊處理。 雜湊的結果會決定邏輯分割區。 Azure Cosmos DB 會在實體分割區上平均配置分割區索引鍵雜湊的索引鍵空間。
僅允許針對單一邏輯分割區中的項目進行交易 (在預存程序或觸發程序中)。
複本集
每個實體分割區都是由一組複本所組成,也稱為複本集。 每個複本都會裝載資料庫引擎的執行個體。 複本集讓實體分割區內儲存的資料都具耐久性、高度可用且一致。 實體分割區中的每個複本都會繼承分割區的儲存體配額。 實體分割區的所有複本會共同支援配置給該實體分割區的輸送量。 Azure Cosmos DB 會自動管理複本集。
較小的容器通常只需要單一實體分割區,但其仍會有至少 4 個複本。
這張圖顯示邏輯分割區如何對應到全域分散的實體分割區。 映像中的分割集指的是跨多個區域管理相同邏輯分割區索引鍵的一組實體分割區:
選擇分割區索引鍵
分割區索引鍵有兩個元件:分割區索引鍵路徑和分割區索引鍵值。 例如,假設有一個項目 { "userId" : "Andrew", "worksFor": "Microsoft" } 如果您選擇 "userId" 作為分割區索引鍵,則下列為兩個分割區索引鍵元件:
分割區索引鍵路徑 (例如:"/userId")。 分割區索引鍵路徑接受英數字元和底線 (_) 字元。 您也可以使用標準路徑標記法 (/) 來使用巢狀物件。
分割區索引鍵值 (例如:"Andrew")。 分割區索引鍵值可以是字串或數值類型。
若要了解輸送量、儲存體和分割區索引鍵長度的限制,請參閱 Azure Cosmos DB 服務配額一文。
選取分割區索引鍵是 Azure Cosmos DB 中簡單但重要的設計選擇。 選取分割區索引鍵後,您並無法就地變更。 如果您需要變更分割區索引鍵,請將資料移至含有所需分割區索引鍵的新容器。 容器複製工作有助於 完成此程序。 或者,您可以新增 全域次要索引 (預覽版), 以建立具有針對特定查詢模式最佳化的不同分割區索引鍵的資料複本。
對於所有容器而言,分割區索引鍵應該:
是具有不會變更之值的屬性。 如果屬性是您的分割區索引鍵,您便無法更新該屬性的值。
僅包含
String值或轉換成String的數字 (如果可能超出 美國電機電子工程師學會 (IEEE) 754 binary64 規定的雙精確度數值範圍)。 Json 規格說明為什麼因為互通性問題,使用超出此範圍的數字是不好的作法。 這些問題尤其與分割區索引鍵資料行有關,因為其不可變,必須在資料移轉後才能變更。具有高基數。 換句話說,屬性應該要有各式各樣的可能值。
將要求單位 (RU) 耗用量和資料儲存體平均分配給所有邏輯分割區。 分配可確保 RU 使用量與儲存體平均分配在實體分割區。
具有通常不超過 2048 個字節的值,如果未啟用大型分割區金鑰,則為 101 個字節。 如需詳細資訊,請參閱大型分割區金鑰
如果您在 Azure Cosmos DB 中需要多項目 ACID 交易,您必須使用預存程序或觸發程序。 所有 JavaScript 型的預存程序和觸發程序的範圍都是單一邏輯分割區。
附註
如果您只有一個實體分割區,分割區索引鍵的值可能不重要,因為所有查詢都會以相同的實體分割區為目標。
分割區索引鍵的類型
| 資料分割策略 | 使用時機 | 優點 | 缺點 |
|---|---|---|---|
| 一般分割區索引鍵 (例如 CustomerId、OrderId) | 當分割區索引鍵有高基數且符合查詢模式時 (例如,按 CustomerId 篩選) 使用。 適用於查詢主要目標為單一客戶資料的工作負載 (例如,擷取某客戶的所有訂單)。 | 容易管理。 當存取模式符合分割區索引鍵時進行有效率的查詢 (例如,按 CustomerId 查詢所有訂單)。 存取模式一致時防止跨分割區查詢。 | 如果某些值 (例如,一些高流量客戶) 產生的資料量高於其他值,則有經常性存取分割區風險。 如果特定索引鍵的資料量快速增加,可能會達到每個邏輯分割區的 20 GB 限制。 |
| 綜合磁碟分割索引鍵 (例如 CustomerId + OrderDate) | 沒有任何單一欄位同時含有高基數且符合查詢模式時使用。 適合需要將資料平均分散到實體分割區的大量寫入工作負載 (例如,下在相同日期的許多訂單)。 | 協助將資料平均分散到各分割區,減少經常性存取分割區 (例如,依據 CustomerId 和 OrderDate 分散訂單)。 將寫入資料分散到多個分割區,改善輸送量。 | 只篩選一個欄位的查詢 (例如,僅使用 CustomerId) 可能會導致跨分割區查詢。 跨分割區查詢可能會導致較高的 RU 耗用量 (每個存在的實體分割區額外收取 2-3 RU/s 費用),並增加延遲。 |
| 階層式分割區索引鍵 (HPK) (例如 CustomerId/OrderId、StoreId/ProductId) | 需要多層資料分割以支援大型資料集時使用。 適用於在階層的第一層和第二層進行查詢篩選。 | 建立多個資料分割層級,有助於避免 20 GB 的限制。 在這兩個階層層級上進行有效率的查詢 (例如,先按 CustomerID 進行篩選,再按 OrderID 進行篩選)。 讓目標鎖定頂層的查詢盡可能減少跨分割區查詢 (例如,從特定 CustomerID 擷取所有資料)。 | 需要仔細規劃,確保第一層索引鍵具有高基數且包含在大部分查詢中。 管理的複雜性高於一般分割區索引鍵。 如果查詢與階層不一致 (例如,當 CustomerID 為第一個層級時,僅按 OrderID 進行篩選),查詢效能可能會受到影響。 |
| 全域次要索引 (GSI) - 預覽 (例如,來源使用 CustomerId,GSI 使用 OrderId) | 當您找不到適用於所有查詢模式的單一分割區索引鍵時使用。 非常適合需要有效率地依多個獨立屬性進行查詢,且具有大量實體分割區的工作負載。 | 使用 GSI 分割區索引鍵時可避免跨分割區查詢。 允許對相同資料進行多個查詢模式,並從來源容器自動同步。 工作負載之間的效能隔離。 | 每個 GSI 都有額外的儲存和 RU 成本。 GSI 中的資料最終與來源容器一致。 |
大量讀取容器的分割區索引鍵
對於大部分的容器而言,您在選擇分割區索引鍵時必須考慮上述所有準則。 不過,對於大型的大量讀取容器而言,建議您選擇經常在查詢中顯示為篩選的分割區索引鍵。 在篩選述詞中納入分割區索引鍵,可以有效率地將查詢路由傳送至相關的實體分割區。
如果您工作負載大部分的要求都是查詢,且大部分的查詢針對相同的屬性都使用相等的篩選,則這個屬性便是不錯的分割區索引鍵選擇。 例如,如果您經常執行會篩選 UserID 的查詢,則選取 UserID 作為分割區索引鍵將能減少跨分割區查詢的數目。
如果容器很小,實體分割區數量可能不足以讓您需要擔心跨分割區查詢的效能。 Azure Cosmos DB 中最小的容器只需要一或兩個實體分割區。
如果您的容器可能會成長為具備多個實體分割區,則您應該挑選能將跨分割區查詢最小化的分割區索引鍵。 如果下列任一情況成立,您的容器會需要多個實體分割區:
容器佈建的要求單位數超過 30,000
您的容器會儲存超過 100 GB 的資料
跨分割區查詢的全域次要索引
如果您的應用程式需要有效率地使用多個不同的屬性來查詢資料, 全域次要索引 (預覽版) 提供針對資料集使用一個分割區索引鍵策略的替代方案。 全域次要索引是具有不同分割區索引鍵的附加容器,會自動與來源容器中的資料同步。
在下列情況下,請考慮全域二級索引:
- 您有多個查詢模式,無法由單一分割區索引鍵策略滿足
- 變更現有的分區金鑰會造成干擾
- 您需要將分析或搜尋工作負載與交易作業隔離
全域次要索引透過儲存具有針對特定查詢模式最佳化的不同分割區索引鍵的相同資料,有助於避免跨分割區查詢。 此方法可大幅減少 RU 耗用量,並改善僅靠分割區鍵優化不足的情境下的查詢效能。
使用項目識別碼作為分割區索引鍵
附註
本節主要適用於 NoSQL 的 API。 其他 API,例如 Gremlin 的 API,不支援唯一識別碼作為分割區金鑰。
如果容器的屬性含有各式各樣的可能值,該屬性可能會是不錯的分割區索引鍵選擇。 這類屬性的範例是項目識別碼。 對於小型的大量讀取容器或任何大小的大量寫入容器而言,項目識別碼 (/id) 向來就是分割區索引鍵的絕佳選擇。
容器中的每個項目都會有作為系統屬性的項目識別碼。 您可能會有代表您項目邏輯識別碼的其他屬性。 在許多情況下,這些唯一識別碼也是絕佳的分割區索引鍵選擇,其原因與項目識別碼相同。
項目識別碼是很棒的分割區索引鍵選擇,原因如下:
- 具有各式各樣可能的值 (每個項目都有一個唯一的項目識別碼)。
- 因為每個項目都有唯一的項目識別碼,所以項目識別碼很適合用來平均分配 RU 耗用量和資料儲存體。
- 您可以輕鬆地進行有效的點讀取,因為只要知道某個項目的項目識別碼,就能知道其分割區索引鍵。
選取項目識別碼作為分割區索引鍵時,請考慮下列注意事項:
- 如果項目識別碼是分割區索引鍵,則會成為整個容器的唯一識別碼。 您無法建立含有重複識別碼的項目。
- 如果您有具有許多實體分割區的大量讀取容器,如果查詢具有搭配項目識別碼的相等篩選,其便會更加有效率。
- 預存程序或觸發程序不能鎖定多個邏輯分割區為目標。