Cosmos DB按ID与Country分区的查询RU消耗为何一致?
问题背景
我使用包含1571个文档的Volcano JSON样本,在Cosmos DB模拟器中创建了两个容器:
- 一个以
ID为分区键(容器名VolcanoesById) - 另一个以
Country为分区键(容器名VolcanoesByCountry)
执行以下查询语句:
select * from VolcanoesById c where c.Country = 'Japan' select * from VolcanoesByCountry c where c.Country = 'Japan'
模拟器返回的请求费用(Request Charge)均为6.25 RUs,其余指标也基本一致:
按ID分区的容器指标
- 请求费用 - 6.25 RUs
- 结果数 - 111
- 检索文档大小 - 56255 bytes
- 输出文档数 - 111
- 输出文档大小 - 56416 bytes
- 索引命中文档数 - 111
- 索引查找时间 - 0.13 ms
- 文档加载时间 - 0.5 ms
- 查询引擎执行时间 - 0.09 ms
按Country分区的容器指标
- 请求费用 - 6.25 RUs
- 结果数 - 111
- 检索文档大小 - 56255 bytes
- 输出文档数 - 111
- 输出文档大小 - 56416 bytes
- 索引命中文档数 - 111
- 索引查找时间 - 10.96 ms
- 文档加载时间 - 0.46 ms
- 查询引擎执行时间 - 0.11 ms
我原本预期以Country为分区键的查询RU消耗会更低,请问这是为什么?
解答
出现这种情况的核心原因在于数据集规模、索引机制以及模拟器环境的特殊性,具体分析如下:
极小数据集稀释了分区键优势
你的数据集仅包含1571个文档,属于超小规模。Cosmos DB的物理分区默认最大存储容量为10GB,这么小的数据量只会被分配到单个物理分区中——也就是说,即使你选择ID作为分区键,所有文档实际都在同一个物理分区里,查询不需要跨多个物理分区扫描,自然不会产生额外的跨分区RU开销。此时两种分区策略的查询本质上都是单分区操作,RU消耗自然持平。默认索引抵消了跨分区查询成本
两个容器都启用了Cosmos DB默认的范围索引,Country字段被自动纳入索引。对于VolcanoesById容器,查询时可以直接通过索引快速定位到所有Country='Japan'的文档,无需遍历整个数据集,这就把跨逻辑分区查询的额外成本降到了最低,最终RU消耗和单分区查询(VolcanoesByCountry容器)一致。模拟器环境的理想性
Cosmos DB模拟器是本地无资源限制的模拟环境,没有生产环境中的网络延迟、多租户资源竞争、物理节点调度等额外开销。在这种理想环境下,即使存在微小的跨分区查询成本,也会被忽略,导致两种分区策略的RU差异无法显现。
验证分区键优势的建议
如果想看到Country作为分区键的RU优势,可以尝试:
- 大幅扩大数据集规模(例如到百万级文档),让
VolcanoesById容器被拆分到多个物理分区,此时跨分区扫描的RU开销会显著增加 - 测试无索引的查询场景:禁用
Country字段的索引后,VolcanoesById容器需要全表扫描,RU消耗会远高于VolcanoesByCountry容器的单分区扫描
内容的提问来源于stack exchange,提问作者Brian Mains

