首页 文章

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

提问于
浏览
2

我正在做一些研发,将产品目录移到CosmosDB中 .

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

  • 产品ID(GUID)

  • 产品名称

  • 制造商

制造商将登录此系统,并且只能查询自己的数据,因此每次查询都会有一个 ManufacturerId = SINGLE_VALUE 过滤器 .

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

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

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

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

2 回答

  • 0

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

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

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

    其次,只有具有相同分区键的文档才能保证在同一分区上可用,如果您需要将它们包含在事务存储过程中 . 'guid'的子串也对这种情况没有帮助 .

    我几乎总是使用基于'identifier'的分区键,例如你的产品ID . 这不是文件本身的't always correspond to the ' id' . 有时我有多个文档,其内容与同一内容相关 . 例如,如果我从另一个系统同步了一些产品信息,那么同步作业如果使用upsert则效率最高 - 但由于当前缺少CosmosDB中的部分更新支持(请参阅user voice),整个文档需要被插入 . 因此,在这种情况下,我有一个文档用于同步信息,另一个文档用于其他信息 . 这看起来像是这样的:

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

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

    我在实现修订系统时也使用了这种模式,因此保证同一逻辑文档的所有修订都放在同一个分区上 . 在这种情况下,文档具有对于所有修订都相同的“文档”,并且文档的实际“id”是添加了修订号的文档ID .

    如果您还没有,请在这里查看'Design for Partitioning':https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data

  • 1

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

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

    如果你确实认为你是可能的 . 例:Manufacturer = General Motors ,Category = SUVs ,然后在表示 Manufacturer_Category 的自定义字符串字段上进行分区 . 此复合分区键是读/写速度和分区 balancer 的最佳折衷方案 .

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

相关问题