【问题标题】:Partition key for DocumentDBDocumentDB 的分区键
【发布时间】:2017-06-22 14:50:33
【问题描述】:

我有一个关于 DocumentDB 分区键选择的问题。 我有 UserId、DeviceId 和 WhatId 的数据。 UserId 参数将始终在查询中,因此我选择了 UserId 作为分区键。但是我有一个用户(数百万个实体)的大量数据,当我使用指定的分区键创建像 "SELECT * FROM c WHERE c.DeviceId = @DeviceId" 这样的 quety 时,它需要很长时间(大约 220 000 个返回的实体大约需要 6 分钟)。 也许选择例如 DeviceId 作为分区键并同时对几个分区进行查询会更有效 (指定 EnableCrossPartitionQuery = true 和 MaxDegreeOfParallelism = 分区计数)? 或者,为每个用户使用单独的集合是个好主意?

【问题讨论】:

  • 并不是说这回答了您的问题,但是...我认为,每当您尝试检索 25 万个实体时,您可能需要重新考虑您的数据访问模式。此外,“SELECT *”是另一种代码气味。如果您尝试将这么多数据移动到应用层,我看不出您选择的分区键会有什么不同。
  • 谢谢。 SELECT * 只是一个简单的例子,对不起。我将使用SELECT c.Value。这个问题只是关于选择分区键,因为 azure 文档站点上的信息对我来说有点抽象。所有这些测量只是为了根据查询进行性能比较。

标签: azure-cosmosdb partition


【解决方案1】:

这可能会有所帮助,但我认为每个用户的分区不会解决您的问题,因为您基本上已经在幕后。

您可以尝试使用分区键来改善并行性,但在我的经验中,这最多可以让您提高 2 到 5 倍。够了吗?

要获得更显着的改进,您通常必须求助于选择性的非规范化和/或缓存。

【讨论】:

  • 我已将分区键更改为 DeviceId 并尝试进行类似SELECT c.Value FROM c WHERE c.UserId = @userId and c.WhateverId = @WhateverId 的查询。 19845 个返回的实体花费了 4.6。那没问题。但是当我尝试使用像SELECT c.Value FROM c WHERE c.UserId = @userId and c.DeviceId = @DeviceId 这样的分区键进行查询时,几乎相同数量的返回实体需要大约 27 秒。这并不好,因为使用 DeviceId 的查询更频繁地使用。我知道这是因为当我们指定分区键时没有并行性。我应该考虑另一个pk
  • 关键是你必须不断尝试。不要忘记在您的实验中包括索引调整。默认索引键关闭数据的前 3 个字节。如果变化不够大,您可能会有一个索引热点。
  • 你的意思是,如果我有很多以相同字符开头的键,就会发生这种情况,对吧。
  • 是的,开头的字符相同
【解决方案2】:

我知道这有点老了,但是为了其他人的利益,来到这个话题......

根据您的描述,我假设这些设备大多是用户独有的。通常建议在用户 ID 之类的东西上进行分区,如果你有一个很好的分区,比如呼叫中心应用程序,对给定的用户 ID 有很多查询,并且希望查找不超过几百个条目。在这种情况下,可以从单个分区中快速提取数据,而无需跨分区整理数据的开销。但是,如果您有数百万条用户记录,那么根据用户 ID 进行分区可能是最糟糕的选择,因为从单个分区中提取大量数据很快就会超过排序规则的开销。在这种情况下,您希望将用户数据尽可能均匀地分布在所有分区上。除非每个用户都有 25 台以上使用类似的设备,否则 Device Id 可能也不是一个好的选择。

在像您这样的情况下,我通常会发现系统生成的递增键(例如 Event Id 或 Transaction Id)是最佳选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多