Azure Cosmos DB 中的資料分割和水平調整
適用於:NoSQL MongoDB Cassandra Gremlin 桌子
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 的限制,因為每個邏輯分割區只對應到一個實體分割區。
總資料儲存體 (每個個別的實體分割區最多可以儲 50GB 的資料)。
注意
實體分割區是系統的內部實作,而且完全由 Azure Cosmos DB 管理。 開發解決方案時,請勿專注於實體分割區,因為您無法加以控制。 相反地,請將焦點放在您的分割區索引鍵上。 如果您選擇會將輸送量耗用量平均分配給邏輯分割區的分割區索引鍵,您將可確保跨實體分割區的輸送量耗用量是平衡的。
您容器中的實體分割區總數沒有任何限制。 當您佈建的輸送量或資料大小增加時,Azure Cosmos DB 將會分割現有的實體分割區,以自動建立新的實體分割區。 實體分割區分割不會影響應用程式的可用性。 分割實體分割區之後,單一邏輯分割區內的所有資料仍會儲存在相同的實體分割區上。 實體分割區分割只會在邏輯分割區與實體分割區之間建立新對應。
為容器佈建的輸送量會在實體分割區之間平均分配。 不平均散發要求的分割區金鑰設計,可能會導致太多要求導向至變成「經常性」的小型分割區子集。經常性分割會導致佈建輸送量的使用效率不佳,這可能會導致速率限制和更高的成本。
例如,請考慮指定為分割區金鑰的路徑 /foodGroup
包含在內的容器。 容器可以有任意數目的實體分割區,但在此範例中,我們假設它有三個。 單一實體分割區可以包含多個分割區金鑰。 例如,最大的實體分割區可能包含前三個最大大小邏輯分割區:Beef Products
、Vegetable and Vegetable Products
和 Soups, Sauces, and Gravies
。
如果您指派 18,000 每秒要求單位 (RU/s) 的輸送量,則這三個實體分割區個別都可以利用總佈建輸送量的 1/3。 在選取的實體分割區內,邏輯分割區索引鍵 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")。 分割區索引鍵路徑接受英數字元和底線 (_) 字元。 您也可以透過標準路徑標記法 (/) 來使用朝狀物件。
分割區索引鍵值 (例如:"Andrew")。 分割區索引鍵值可以是字串或數值類型。
若要了解輸送量、儲存體和分割區索引鍵長度的限制,請參閱 Azure Cosmos DB 服務配額一文。
選取分割區索引鍵是 Azure Cosmos DB 中簡單但重要的設計選擇。 當您選取分割區索引鍵之後,就無法就地變更。 如果您必須變更分割區索引鍵,則應該使用新的所需分割區索引鍵來將資料移至新的容器。 (容器複製工作可協助進行此程序。)
針對所有容器,分割區索引鍵應為:
是具有不會變更之值的屬性。 如果屬性是分割區索引鍵,您便無法更新該屬性的值。
應只包含
String
值,或是如果數字可能超出 IEEE 754 binary64 所述的雙精確度數字的界限,則數字應最好轉換為String
。 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/秒額外費用),並新增延遲。 |
階層式分割區索引鍵 (HPK) (例如 CustomerId/OrderId、StoreId/ProductId) | - 當您需要多層級的數據分割來支援大規模資料集時,請使用 。 - 當查詢篩選階層的第一層和第二層時,理想。 |
- 藉由建立多個層級的數據分割,協助避免 20 GB 的限制。 - 對兩個階層層級進行有效率的查詢(例如,先依 CustomerID 篩選,再依 OrderID 篩選)。 - 將目標為最上層查詢的跨分割區查詢最小化(例如,從特定 CustomerID 擷取所有數據)。 |
- 需要仔細規劃,以確保第一層索引鍵具有高基數,且包含在大部分查詢中。 - 比一般分割區索引鍵更複雜。 - 如果查詢與階層不一致(例如,只有在 CustomerID 是第一層時,僅依 OrderID 進行篩選),查詢效能可能會受到影響。 |
大量讀取容器的分割區索引鍵
對於大部分的容器而言,在挑選分割區索引鍵時,您只需要考慮上述準則。 不過,對於大型的大量讀取容器而言,建議您選擇經常在查詢中顯示為篩選的分割區索引鍵。 您可以透過在篩選述詞中包含分割區索引鍵,僅將查詢有效傳送至相關實體分割區。
如果您工作負載大部分的要求都是查詢,且大部分的查詢針對相同的屬性都具有相等的篩選,則這個屬性便是不錯的分割區索引鍵選擇。 例如,如果您經常執行會篩選 UserID
的查詢,則選取 UserID
作為分割區索引鍵將能減少跨分割區查詢的數目。
但是,如果您的容器很小,您的實體分割區可能不足以讓您需要擔心跨分割區查詢所帶來的效能。 Azure Cosmos DB 中最小的容器只需要一或兩個實體分割區。
如果您的容器可能會成長到多個實體分割區,則您應該確定您挑選可最小化跨分割區查詢的分割區索引鍵。 當下列任一項為真時,您的容器將需要一個以上的實體分割區:
您的容器已佈建超過 30,000 RU
您的容器會儲存超過 100 GB 的資料
使用項目識別碼作為分割區索引鍵
注意
本節主要適用於 NoSQL 的 API。 其他 API,例如 Gremlin 的 API,不支援唯一識別碼作為分割區金鑰。
如果您的容器具有具備各式各樣可能值的屬性,該屬性便可能很適合作為分割區索引鍵。 這類屬性的其中一個可能範例是項目識別碼。 對於小型的大量讀取容器或任何大小的大量寫入容器而言,項目識別碼 (/id
) 向來就是分割區索引鍵的絕佳選擇。
容器中的每個項目都有系統屬性項目識別碼。 您可能會有代表您項目邏輯識別碼的其他屬性。 在許多情況下,這些識別碼也是絕佳的分割區索引鍵選擇,其原因與項目識別碼相同。
項目識別碼是絕佳的分割區索引鍵選擇,原因如下:
- 有各種可能的值 (每個項目有一個唯一項目識別碼)。
- 因為每個項目都有唯一的項目識別碼,所以項目識別碼很適合用來平均分配 RU 耗用量和資料儲存體。
- 您可以輕鬆地進行有效的點讀取,因為只要知道某個項目的項目識別碼,就能知道其分割區索引鍵。
選取項目識別碼作為分割區索引鍵時,需要考慮的某些事項包括:
- 如果項目識別碼是分割區索引鍵,其會成為整個容器的唯一識別碼。 您無法建立具有重複項目識別碼的項目。
- 如果您有具有許多實體分割區的大量讀取容器,如果查詢具有搭配項目識別碼的相等篩選,其便會更加有效率。
- 您無法針對多個邏輯分割區執行預存程序或觸發程序。