仅每个分片键(分区键)的Cosmos DB值唯一性点

时间:2020-10-11 15:25:49

标签: mongodb azure-cosmosdb sharding uniqueidentifier azure-cosmosdb-mongoapi

Microsoft的Managing indexing in Azure Cosmos DB's API for MongoDB文档指出:

Azure Cosmos DB的适用于MongoDB服务器3.6版的API自动 索引_id字段,不能删除。自动 强制_id字段每个分片键的唯一性。

我对“ 每个分片键”部分背后的原因感到困惑。我将其视为“您是唯一字段,根本不会在全局上是唯一的”,因为如果我正确理解它,并且如果我将Guid字段name设置为唯一,将local credits = {} local function get_credit () io.write 'Type name and credit or just press Enter to finish: ' return io.read():match '^([^%d%s]+)%s*(%d+)$' end for name, credit in get_credit do -- note the absence of (). credits [name] = tonumber (credit) end -- Show credits: for name, credit in pairs (credits) do print (name .. "'s credit is " .. tostring (credit)) end 字段设置为分区键,那么我可以让2个元素具有相同的ID,前提是它们恰好属于2个不同的用户。

是否无法选择正确的分区键?因为在我的理解中,分区键应该是最常用于过滤数据的字段。但是,如果我只需要具有ID字段值就可以从数据库中选择数据呢?还是查询所有用户的数据?

这是否是我需要接受的分布式系统的固有限制,因此需要重塑设计数据库和对其访问进行编程的过程?在这种情况下,应该是:总是不仅通过_id字段,而且首先通过userId字段从该集合中查询数据?而不是将我的_id字段单独视为标识符,而是将标识符视为userId_id的组合?

1 个答案:

答案 0 :(得分:1)

TL; DR

这是否是我需要接受的分布式系统的固有限制,因此需要重塑设计数据库和对其访问进行编程的过程?在这种情况下,将是:总是不仅通过_id字段,而且首先通过userId字段从此集合查询数据?而不是将我的_id字段单独视为标识符,而是将标识符视为userId和_id的组合?

是的。通常。

长版

虽然这个id not字段不是唯一的乍一看并不直观,但考虑到CosmosDB寻求精确的GET / PUT操作的无限扩展性,这实际上是有道理的。这要求分区独立运行,这就是很多魔术的来源。如果id或其他唯一约束唯一性将在全局范围内实施,则每次文档更改都必须与所有其他分区进行协调,并且不再是无尽的最佳或可预测的 < / p>

我还认为,这种分离数据的设计决策与CosmosDB的无模式分布式思维方式是一致的。如果您使用CosmosDB,请接受此操作,并避免尝试对其施加强制的跨文档关系约束。而是在数据/ api设计和客户端逻辑层中管理它们。例如,通过使用GUID作为ID。

关于分区键。

是否无法选择正确的分区键?分区键应该是最常用于过滤数据的字段。

这取决于;)。您还必须考虑到最差的查询性能,而不仅仅是“最常用”的查询。确保MOST查询可以直接进入正确的分区,这意味着在进行这些查询之前,您必须知道确切的目标分区键,即使对于那些“按ID获取”查询也是如此。在实际数据集上衡量左跨分区查询的成本。

很难说userId是否是一个好的密钥。它很可能是事先已知的,并且可以包含在通过ID的查询中,因此从这个意义上讲是很好的。但您还应该考虑:

  • 热分区-所有单个用户查询都将转到单个分区,而无法在那里扩展。
  • 分区大小-单用户数据最有可能增长和增长。分区具有最大大小限制,并且随着时间的推移,在这些目标分区内工作将变得更加昂贵。

因此,如果可能的话,我将定义较小的分区以进一步分散负载。也许考虑使用using a composite partition key or similar tactics将用户分区拆分为多个较小的分区。或到having id itself a partition key的极端,这对于写和获取ID很有用,但对其他所有东西都不是最佳选择。

..始终确保手头有选定的分区键。