在CosmosDB中使用GUID的子字符串作为分区键是一个坏主意吗?

时间:2018-02-28 14:07:47

标签: azure-cosmosdb

我正在做一些R& D将产品目录移到CosmosDB中。

用最简单的术语来说,产品文档将具有:

  • 产品ID(GUID)
  • 产品名称
  • 制造商

制造商将登录此系统,并且只能查询自己的数据,因此每次查询都会有 total_bill tip sex smoker day time size 3 23.68 3.31 Male No Sun Dinner 2 4 24.59 3.61 Female No Sun Dinner 4 5 25.29 4.71 Male No Sun Dinner 4 7 26.88 3.12 Male No Sun Dinner 4 11 35.26 5.00 Female No Sun Dinner 4 15 21.58 3.92 Male No Sun Dinner 2 19 20.65 3.35 Male No Sat Dinner 3 23 39.42 7.58 Male No Sat Dinner 4 28 21.70 4.30 Male No Sat Dinner 2 33 20.69 2.45 Female No Sat Dinner 4 35 24.06 3.60 Male No Sat Dinner 3 39 31.27 5.00 Male No Sat Dinner 3 44 30.40 5.60 Male No Sun Dinner 4 46 22.23 5.00 Male No Sun Dinner 2 47 32.40 6.00 Male No Sun Dinner 4 48 28.55 2.05 Male No Sun Dinner 3 52 34.81 5.20 Female No Sun Dinner 4 54 25.56 4.34 Male No Sun Dinner 4 56 38.01 3.00 Male Yes Sat Dinner 4 57 26.41 1.50 Female No Sat Dinner 2 59 48.27 6.73 Male No Sat Dinner 4 72 26.86 3.14 Female Yes Sat Dinner 2 73 25.28 5.00 Female Yes Sat Dinner 2 77 27.20 4.00 Male No Thur Lunch 4 78 22.76 3.00 Male No Thur Lunch 2 80 19.44 3.00 Male Yes Thur Lunch 2 83 32.68 5.00 Male Yes Thur Lunch 2 85 34.83 5.17 Female No Thur Lunch 4 87 18.28 4.00 Male No Thur Lunch 2 88 24.71 5.85 Male No Thur Lunch 2 .. ... ... ... ... ... ... ... 180 34.65 3.68 Male Yes Sun Dinner 4 181 23.33 5.65 Male Yes Sun Dinner 2 182 45.35 3.50 Male Yes Sun Dinner 3 183 23.17 6.50 Male Yes Sun Dinner 4 184 40.55 3.00 Male Yes Sun Dinner 2 187 30.46 2.00 Male Yes Sun Dinner 5 189 23.10 4.00 Male Yes Sun Dinner 3 191 19.81 4.19 Female Yes Thur Lunch 2 192 28.44 2.56 Male Yes Thur Lunch 2 197 43.11 5.00 Female Yes Thur Lunch 4 200 18.71 4.00 Male Yes Thur Lunch 3 204 20.53 4.00 Male Yes Thur Lunch 4 206 26.59 3.41 Male Yes Sat Dinner 3 207 38.73 3.00 Male Yes Sat Dinner 4 208 24.27 2.03 Male Yes Sat Dinner 2 210 30.06 2.00 Male Yes Sat Dinner 3 211 25.89 5.16 Male Yes Sat Dinner 4 212 48.33 9.00 Male No Sat Dinner 4 214 28.17 6.50 Female Yes Sat Dinner 3 216 28.15 3.00 Male Yes Sat Dinner 5 219 30.14 3.09 Female Yes Sat Dinner 4 227 20.45 3.00 Male No Sat Dinner 4 229 22.12 2.88 Female Yes Sat Dinner 2 230 24.01 2.00 Male Yes Sat Dinner 4 237 32.83 1.17 Male Yes Sat Dinner 2 238 35.83 4.67 Female No Sat Dinner 3 239 29.03 5.92 Male No Sat Dinner 3 240 27.18 2.00 Female Yes Sat Dinner 2 241 22.67 2.00 Male Yes Sat Dinner 2 243 18.78 3.00 Female No Thur Dinner 2 [97 rows x 7 columns] 过滤器。

在回顾宇宙文档时,重新选择正确的分区策略,似乎有2个要点。   - 选择具有高基数的分区键   - 选择一个分区键,可以均匀分布数据。

在上面的场景中,选择产品ID作为PartitionKey将是非常极端的...每个逻辑分区1个文档。 另一方面,选择制造商也不会很好,因为这不会导致均匀分布(一些制造商有10个产品,其他制造商有10万个)

确保均匀分布的一种方法是获取GUID的前4个字符并将其用作PartitionKey。 (所以最多4096个分区)。根据我现有的数据集,这确实可以实现均匀的数据分布。但我想知道这样做是否有任何缺点。

使用整个productId作为PartitionKey(每个分区1个doc)是否有任何缺点,因为它们似乎表明这是存储用户配置文件的系统的有效方法。这种方法是否会影响在同一搜索中搜索多个产品。

2 个答案:

答案 0 :(得分:2)

使用每个文档唯一的密钥是确保均匀分发以支持高性能的好方法 - 这样可以使完整的产品ID成为一个很好的选择。我不相信您可以通过使用完整guid的子字符串作为分区键来获得任何优势 - 而且您将限制可用分区的最大数量。

那么为什么不总是使用唯一标识符作为分区键?

首先,如果向查询添加分区键,则无需启用跨分区查询,您将获得较低的总体查询成本(RU / s)。因此,如果您可以设计分区键以减少对跨分区查询的需求,则可以节省RU / s。我不会想到一个guid'的子串。帮助你,因为guid的随机性不会以你可以利用的方式分发文档进行有效的查询。

其次,如果需要将具有相同分区键的文档放在事务存储过程中,则只保证在同一分区上可以使用这些文档。 guid'的一个子串。对这种情况也没有帮助。

我几乎总是使用'标识符'基于分区键,例如您的产品ID。这并不总是对应于' id'文件本身。有时我有多个文档,其内容与同一内容相关。例如,如果我从另一个系统同步了一些产品信息,那么如果同步作业使用upsert,那么该同步作业可能是最有效的 - 但由于当前缺乏CosmosDB中的部分更新支持(请参阅user voice),整个文档需要坚持下去。因此,在这种情况下,我有一个文档用于同步信息,另一个文档用于其他信息。这看起来像是:

{
  "id": "12345:myinfo",
  "productid":"12345",
  "info":{}
  "type":"myinfotype"
},
{
  "id": "12345:vendorsync",
  "productid":"12345",
  "syncedinfo":{},
  "type":"vendorsync"
}

这里的产品ID是分区键,我有几个与该产品相关的不同文档,我知道它们将驻留在同一个分区上,因此我可以有效地查询它们或将它们包含在事务中。

我在实现修订系统时也使用了这种模式,因此保证同一逻辑文档的所有修订都放在同一个分区上。在这种情况下,该文件有一个" documentid"对于所有修订都是一样的,实际的" id"该文档是添加了修订号的文档ID。

还请查看“设计分区”和“#39;在这里,如果你还没有: https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data

答案 1 :(得分:2)

根据您的文档大小和制造商的整体文档数量,我可能会使用ManufacturerID作为您的PartitionKey。

是不平衡的,是的。但只要最大的制造商能够保持在分区限制之下(截至本文撰写时为12.5GB),那么您将获得非常高效的查询。如果您选择了GUID字段,那么您将始终必须使用跨分区查询,这意味着需要更高的RU,因此成本更高且速度更慢。我在这里做的假设是较大的制造商可能会执行更多的查询。

如果你确实认为你会遇到这个分区限制,那么如果可能的话,其他一些想法将被划分为每个制造商的子类别。示例:制造商= General Motors,类别= SUVs,然后在代表Manufacturer_Category的自定义字符串字段上进行分区。此复合分区键是读/写速度和分区平衡的最佳折衷方案。

-FYI:无需使用GUID的子字符串作为partitionKey,因为CosmosDB会自动将您的值哈希到您拥有的物理分区数的相应分区键范围内。