【问题标题】:Why do Azure Cosmos queries have higher RUs when specifying the partition key?为什么 Azure Cosmos 查询在指定分区键时具有更高的 RU?
【发布时间】:2021-01-02 22:30:03
【问题描述】:

我有一个类似于this one 的问题。基本上,我一直在测试使用分区键的不同方法,并注意到在任何时候,查询中引用的分区键越多,RU 就越高。它非常一致,甚至不关心如何使用分区键。所以我把它缩小到测试的基本查询。

首先,这个数据库有大约 850K 文档,大小都超过 1KB。分区键基本上是数字形式的id的100模,设置为/partitionKey,容器使用默认的索引策略:

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/*"
        }
    ],
    "excludedPaths": [
        {
            "path": "/\"_etag\"/?"
        }
    ]
}

这是我的基本查询测试:

SELECT c.id, c.partitionKey
FROM c
WHERE c.partitionKey = 99 AND c.id = '99999'
-- Yields One Document; Actual Request Charge: 2.95 RUs
SELECT c.id, c.partitionKey
FROM c
WHERE c.id = '99999'
-- Yields One Document; Actual Request Charge: 2.85 RUs

Azure Cosmos 文档说没有分区键,查询将“fan out”到所有逻辑分区。因此,我完全希望第一个查询针对单个分区,第二个查询针对所有分区,这意味着第一个查询应该具有较低的 RU。我想我正在使用 RU 结果作为 Cosmos 是否正在扇出并扫描每个分区的证据,并将其与文档中所说的应该发生的情况进行比较。

我知道这些结果仅相差 0.1 RU。但我的观点是查询越复杂,差异就越大。例如,下面是另一个稍微复杂一点的查询:

SELECT c.id, c.partitionKey
FROM c
WHERE (c.partitionKey = 98 OR c.partitionKey = 99) AND c.id = '99999'
-- Yields One Document; Actual Request Charge: 3.05 RUs

请注意,RU 会继续增长,并且根本没有指定分区键。相反,我希望上述查询仅针对两个分区,而没有分区键检查据称会散播到所有分区。

我开始怀疑分区键检查发生在 其他过滤器之后(或在每个分区扫描内)。例如,返回第一个查询但将 id 更改为不存在的内容:

SELECT c.id, c.partitionKey
FROM c
WHERE c.partitionKey = 99 AND c.id = '99999x'
-- Yields Zero Documents; Actual Request Charge: 2.79 RUs
SELECT c.id, c.partitionKey
FROM c
WHERE c.id = '99999x'
-- Yields Zero Documents; Actual Request Charge: 2.79 RUs

请注意,RU 完全相同,并且两者(包括具有分区过滤器的 的 RU 都比文档存在时的 RU 少。这似乎是对结果执行分区过滤器的症状,而不是限制扇出。但这不是文档所说的。

为什么在指定分区键时 Cosmos 具有更高的 RU?

【问题讨论】:

  • 我怀疑这是因为为查询指定分区键的常用方法是在查询旁边作为标题或参数,而不是作为查询 WHERE 子句的一部分。您对查询指标有何看法? docs.microsoft.com/en-us/azure/cosmos-db/…
  • 这也可能是在查询中提供id 的副作用。好奇当另一个过滤器不是id 时会发生什么?此外,如果小于 50 GB docs.microsoft.com/en-us/azure/cosmos-db/…,您的数据实际上可能位于单个物理分区上

标签: azure azure-cosmosdb azure-cosmosdb-sqlapi


【解决方案1】:

就像评论中指定的那样,如果您是通过门户(或通过代码,但使用您提供的查询)进行测试,它将变得更加昂贵,因为您不是在查询特定的分区,而是在查询所有内容然后引入另一个过滤器,费用更高。

您应该做的 - 是在代码中使用正确的方式来传递分区键。我的结果非常令人印象深刻:3 ru\s 有 PK 和 20.000 ru\s 没有 PK,所以我很有信心 intworks(我有一个非常大的数据集)

【讨论】:

  • 我提供的证据似乎你和诺亚所说的都是真的。但如果这是真的,那么the documentation 就不会是真的。它说我可以在查询中指定一个分区键,甚至可以对多个分区使用“IN”条件。尽管如此,我还是构建了一个小程序并对其进行了测试。无论 QueryRequestOptions 是否具有分区键,或者它是否在查询本身中,或者两者都存在,我都会为我的查询获得确切的 RU。这告诉我奇怪的行为是由其他原因引起的......
  • 同意,表面上看似乎没有道理。我不确定查询中的 PK 与作为标头的 PK 之间是否存在差异。我能想到的唯一解释是你的数据都在一个分区中,所以在这种情况下没有发生跨分区,只是额外的子句(分区键)的费用。也许 Cosmos 团队可以澄清一下。
  • 哦,我想我明白了。即使我有 100 个逻辑分区(通过分区键)和 850k 文档,它们可能仍然位于一个物理分区中。由于无论我在查询中输入什么,它们都会被路由到同一个物理分区,因此添加到查询中会增加复杂性。我没有注意到文档清楚地说明它扇出到 物理 分区,而不是逻辑分区。那么我是否可以得出结论,物理分区中的所有逻辑分区都共享相同的索引?这是有道理的,如果是这样,那么我认为现在一切对我来说都是有意义的。
  • 尝试在请求的属性中而不是在请求本身中指定 PK :)
  • 是的,这就是我在评论 4c 中所说的,我在请求和 QueryRequestOptions 中都进行了尝试,得到了相同的结果。但我认为这里的答案是无论如何它们都被路由到同一个物理分区,并且物理分区上的所有逻辑分区都使用相同的索引。
猜你喜欢
  • 2022-11-12
  • 2020-10-03
  • 2019-05-18
  • 2020-09-25
  • 1970-01-01
  • 1970-01-01
  • 2021-08-14
  • 2019-04-24
  • 1970-01-01
相关资源
最近更新 更多