Azure Cosmos DB 分区键 - 主键是不是可接受?

Posted

技术标签:

【中文标题】Azure Cosmos DB 分区键 - 主键是不是可接受?【英文标题】:Azure Cosmos DB partition key - is primary key acceptable?Azure Cosmos DB 分区键 - 主键是否可接受? 【发布时间】:2018-12-06 20:31:07 【问题描述】:

我们的 Azure Cosmos DB 集合已经变得足够大,需要一个分区键。在对此进行一些阅读时,我得到的印象是最好的分区键是提供均匀分布和更高基数的分区键。来自微软的This article 讨论了它。

使用主键作为分区键可以实现均匀分布,但基数只有 1。如果这是我唯一的选择,这是一件坏事吗?上述文章给出了一些examples,似乎表明在这些情况下应该将主键用作分区键。对于 Azure Cosmos DB,分区是逻辑的,而不是物理的。所以它不会导致每个文档都放在自己的磁盘上,但似乎会导致索引膨胀。

使用主键作为分区键是一种常见的做法吗?它有什么缺点吗?

【问题讨论】:

【参考方案1】:

其实,分区键的选择是一个值得反复权衡的问题。由于选择主键作为分区键是您唯一的选择,因此我只是讨论一些可能的负面因素作为您的参考。

在性能方面,如果你查询的字段不是分区键,你的查询肯定会通过跨分区降低查询性能。可以说,如果数据量小,效果不会太大。

在成本方面,cosmos db主要是按存储空间和RU消耗来收费的。如你所说,选择主键作为分区键会导致更多的索引存储。如果大部分查询是跨分区的,也会导致更多的 RU 消耗。

在使用存储过程、触发器或UDF方面,不能通过存储过程和触发器使用跨分区事务。因为then是分区的,所以在使用的时候需要指定分区键(基数只有1)。

请注意,如果创建了分区键,则以后不能删除或修改它。因此,在您选择之前请考虑并确保您进行数据备份。

更多详情,请参考official doc。

【讨论】:

【参考方案2】:

不,它没有缺点。争取拥有高基数的分区键。不用担心索引或物理分区等。

您可以拥有数百万个分区键和 10 个物理分区。物理分区是由 CosmosDB 在后台创建的。您永远不应该担心物理分区。

【讨论】:

没有。更多的逻辑分区更好。它有助于数据均匀分布。 @RafatSarosh 不是说通过 PK 以外的字段查询成本会更高吗?【参考方案3】:

您可以说主键是分区键最安全、可能也是最合适的选择。

它保证了值的唯一性,除了唯一键之外,这是唯一的实现方式。分配将是均匀的,因为主键将是您的分区键,您将能够使用它来通过阅读而不是查询来检索文档,从而降低了操作速度和成本。

【讨论】:

【参考方案4】:

我认为 MS 在描述如何最好地确定 Cosmos DB 的分区键方面做得并不好 - 特别是如果人们通常建议使用数据库的主键作为分区键(这可能是完全可以接受的) 有时,但我看不出这是正常的)。

在最近的一个项目中,这就是我们决定为系统中的对象识别分区键和项目 ID 的方式。我认为这将适用于许多在其对象上具有自然复合主键候选的系统。

在我们的系统中,每个对象都被限制为一个状态 (StateCode) 和供应商 (VendorId)。从那里,我们有多个实体,如销售订单、客户、小部件……在我们的 SQL Server 实现中,每个表都有一个明显的自然复合主键 StateCode、VendorId、EntityId。在 Cosmos DB 场景中,我们选择 Partition Key 为 StateCode-Vendor-EntityType,Item Id 为 EntityId。这允许在一个分区内查询特定类型的所有实体(保存 RU),同时仍然允许在该分区内进行非常简单的查询(例如,同质实体)。您最终会以这种方式利用复合自然键的所有部分,但允许对实体进行实际分区。

在更复杂的场景中,我们想要跨实体查询给定供应商,我们可以从分区键中删除 EntityType,然后将其移动到项目 ID 中或使用它来过滤正在搜索的对象。这允许在一个分区内进行跨实体查询,但查询本身由于异构实体而稍微复杂一些。

如果实体的整个 ID 都在分区键中,那么您几乎必须始终单独查找项目或在不按 ID 查找时搜索每个分区 - 此时谁在乎您的数据分布的均匀程度如果您必须搜索所有分区,则跨分区。

也许 OP 可以描述更多关于实体的信息 - 它们是否具有自然的复合键候选者(无论它们是否在 SQL 实现中被使用)?如果不是,当前的持久层在通过某个 id 识别系统中的项目方面是什么样的?

【讨论】:

以上是关于Azure Cosmos DB 分区键 - 主键是不是可接受?的主要内容,如果未能解决你的问题,请参考以下文章

Azure Cosmos DB 中托管的 MongoDB:分片与分区

如何为 Cosmos DB 集合中的列创建唯一键?

sql Azure Cosmos DB

Azure 流分析输出到 Azure Cosmos DB

无法使用 Microsoft.EntityFrameworkCore.Cosmos 连接到 Azure Cosmos Db 帐户 - 响应状态代码

Cosmos DB 更改源触发 Azure 函数:租赁丢失异常