为多对多关系场景选择高效的数据模型 Azure Cosmos Db

Picking up an efficient Data model Azure Cosmos Db for many to many relationship scenario

我正在尝试使用 Azure cosmos db 构建应用程序,要求是针对用户存储文章列表。在这种情况下,文章和用户将具有多对多映射。

解决以上两个问题 我计划提供一个名为 userArticles 的容器,其架构以 user/id 作为分区键,并将每篇文章作为单独的文档插入

{
id:guid
type:"article"
article: {
id:1
}
user: {
id: guid
}
}

{
id:guid
type:"article"
article: {
id:2
}
user: {
id: guid
}
}

注: 一篇文章下可以有百万用户 但是一个用户在他们下面的文章可能只有几个 100 我可以牺牲写入性能但不能牺牲读取性能

有什么方法可以更改模型,以便批量 insert/delete 和读取消耗更少 Ru/s 并获得更好的性能?或者拆分模型会有帮助?

这些问题很难在这里回答,因为 NoSQL 设计需要对应用程序本身有深入的了解。我也不确定我在这里遵循您的用例,但会尝试使用这种简单的方法。很可能适合您的解决方案会更加细致。

首先,要维护 many:many 关系,您需要两个容器。一份给用户,一份给文章。

要针对用户的读取性能进行设计,取决于关系的“多”方有多大,您可以将数组中的文章嵌入到每个用户文档中。但是您需要小心,因为最大文档大小为 2MB。此外,随着文章变得越来越大,更新它们的成本也会越来越高,如果用户文档经常更新,维护起来就会非常昂贵。解决方案是引用数据并将文章作为单独的行添加到用户容器中,并使用 /userId 作为所添加文章的分区键。

您最终得到的是一个带有“/userId”分区键、一个用户文档和多个文章文档的“用户”容器。您将需要消除用户和文章实体之间的歧义,因此您需要“类型”属性,如上所示,值为“用户”或“文章”。要获取用户和所有文档,您只需查询用户“Select * from c where c.userId = 'user a'”。如果您只需要用户,请为“type='user a'”添加过滤器。

另请注意,您将需要同样存储在用户容器中的文章所需的数据,以便在按用户查询时可以获得文章的所有属性。

为了保持数据同步,您需要使用 Change Feed 并监控文章容器,然后每当一篇文章更新时,它就会查询用户容器以获取该文章 ID,然后就地更新每篇文章。请注意,这两个查询都将是跨分区的,并且可能会变得非常昂贵,而且您还将更新同一篇文章的多个实​​例,因为您需要为每个用户复制它。但是,请记住,您这样做是因为您正在针对用户的读取进行优化。

现在如果您说文章和用户之间存在一对“百万”的关系并且您希望对文章进行快速查询,那么您将不得不在文章容器中执行相同的操作。在这里您肯定需要将用户添加为单独的行。但是您需要留意您的逻辑分区有多大。最大大小为 20 GB。如果你接近这个或者 articles:users 之间的关系是无限的,那么你将需要一个具有更多基数的分区键。我不能告诉你那是什么,但它应该是你总是查询文章容器的东西,或者你也可以尝试加盐分区键值,“article1_1”,“article1_2” "等

同样的事情也适用于维护用户和文章之间的引用完整性。您将需要使用 Change Feed 来监视用户容器,并且每当更新用户时,您都需要查询该用户的文章容器并更新它的每个实例。