24

来自关系世界的情况显然与 Azure 表存储大不相同。我遇到的第一件大事是如何正确存储多对多关系。

例如,我可能有一个系统来跟踪他们拥有的用户和书籍。我在这里找到了另一篇关于 SO 的帖子,该帖子建议在用户上拥有一个字符串属性,该属性基本上存储了用户拥有的图书 ID 的列表。虽然我知道有时这是一种公认​​的数据存储方式,但问题是 Azure 仅允许您将 64KB 的数据存储在字符串中。这无疑限制了用户可能拥有的图书数量。

另一种可能的解决方案是重复数据。我可能有一个存储系统中所有已知书籍的表。但是当用户需要与一本书关联时,我将图书数据复制到另一个名为 OwnedBooks 的表中,该表与 Book 表基本完全相同,只是它也具有 OwnedByUserID 属性。

还有其他可能的解决方案吗?

除了这个问题,在使用 Azure 表存储时,是否有人对其他模式和实践有什么好的建议?

4

2 回答 2

16

有很多解决方案 - 当然都有缺点:-)

  1. 像在 RDBMS 中一样使用简单的映射表。每行将包含一个 Book 键和一个 User 键。

    然后,要查找用户的所有书籍,您需要在映射表中选择 Book 键,然后对于这些键中的每一个,从 Books 表中选择 Book 实体。您可以使用异步获取并行执行图书检索,但即便如此,该解决方案显然无法扩展。

  2. 使用如上的映射表,但也要在映射表中包含您需要的所有 Book 数据。这是您已经使用 OwnedBooks 表提出的非规范化或“重复数据”解决方案。

    此方法的主要缺点是,如果您需要更新任何 Book 数据,您可能会更新许多实体 - 由于它们位于 Book 本身的单独表中,因此无法在单个事务/批处理(我想您无论如何都会使用用户身份作为映射表中的分区键,这已经排除了该表中的单个批处理更新)。

  3. 将 Book 键存储在用户的单个属性中。同样,您已经建议使用此方法。

    如果不是因为 Azure 当前不支持“包含”类型查询,这实际上不会那么糟糕 - 即,您无法搜索子字符串,所以如果您想找出哪些用户拥有一本特定的书,这是不可能的。有趣的是,Google App Engine 在他们的存储系统中相当透明地支持这一点 - 并且也会为您索引列表。无论如何,您仍然需要使用此方法检索每本书的数据。

  4. 使用 Azure 表存储的“无模式”特性将关联的 Book 键存储为单独的属性。例如,一个用户实体可能如下所示:

    { Name: "User1", Book_4325: true, Book_5123: true }

    而另一个可能看起来像这样:

    { Name: "User2", Book_5346: true, Book_8753: true, Book_6135: true }

    然后,如果您确实想查找拥有特定图书的所有用户,您可以选择该特定属性的真实位置(嗯,它只需要真实存在)。

    这样做的明显缺点是它有点脆弱,您需要修改属性名称中的键,并且您将无法使用 StorageClient 的标准方法 - 您必须自己滚动。此外,Azure 仅支持实体上的 255 个属性。综上所述,我认为它可以很好地扩展——尽管我从未尝试过。

在所有这些选项中,我会说您将要使用的选项 2 将是最好的,只是因为它当前受 Azure 支持,并且您通常可以用更少的查询来完成所有事情。

考虑到原子事务不在窗口中,您只需要仔细检查您的用例来决定如何以及何时更新数据。我几乎可以保证您能够忍受“最终一致”的事情,并且只是考虑到您的映射表可能并不总是 100% 是最新的这一事实。

如果同时更新映射表中的数据和主表中的数据变得过于昂贵,您可以将消息放在队列中并让工作人员角色为您异步执行更新。

于 2009-07-12T07:06:53.613 回答
9

你没有。这是关于 Azure Table的一个很好的综合性白皮书(.docx 链接),其中有一个关于最佳实践的部分。但是,您应该使用 Table 进行非关系属性包或 ORM 类型的设计。如果你想在云中建立关系,你应该使用SQL Azure Database

这是另一篇关于无模式存储与关系的好文章。它适用于不同架构的免费云存储产品,但概念是相同的。

于 2009-07-12T00:33:22.277 回答