首页 > 解决方案 > 为什么这个零结果 Cosmos DB 查询如此昂贵?

问题描述

我正在调查为什么我们在 Cosmos 中耗尽了这么多 RU。我们的写入是预期的 RU 数量,但我们的读取是通过屋顶 - 比我们的写入更多。我试图把它剥离到最简单的场景。在没有结果的分区上查询的单个请求使用了 2000 个 RU。为什么这么贵?

var query = new QueryDefinition("SELECT * FROM c WHERE c.partitionKey = @partionKey ORDER BY c._ts ASC, c.id ASC")
                    .WithParameter("@partionKey", id.Value)

using var queryResultSetIterator = container.GetItemQueryIterator<MyType>(query,
                requestOptions: new QueryRequestOptions
                {
                    PartitionKey = new PartitionKey(id.Value.ToString()),
                });

while (queryResultSetIterator.HasMoreResults)
            {
                foreach (var response in await queryResultSetIterator.ReadNextAsync())
                {
                    yield return response.Data;
                }
            }

集合的分区键是/partitionKey。RU 容量直接在容器上设置,不共享。我们有一个与 where 子句匹配的复合索引 - _ts asc, id asc。虽然我不确定这对不返回任何记录有何影响。

不幸的是,在以这种方式查询时,SDK 似乎没有为您提供使用的 RU,因此我一直在使用 Azure 监视器来观察 RU 的使用情况。

有没有人能够解释为什么这个查询,返回零记录并限制在单个分区会占用 2k RU?

更新:

我刚刚在同一个存储帐户中的另一个数据库实例上运行了这个查询。两者配置相同。DB1 里面有 0MB,DB2 里面有 44MB。对于不返回任何记录的完全相同的操作,DB1 使用了 111 个 RU,DB2 使用了 4730 个 RU——对于相同的无结果查询,增加了 40 多倍。

添加更多细节:一致性设置为一致前缀。是单一区域。

另一个更新:

我已经复制了仅通过 Azure 门户查询的问题,它与容器中的记录数有关。查看查询统计信息,就好像它正在加载容器中的每个文档以搜索分区键。分区键不是最高效的搜索方式吗?Cosmos 不知道在哪里可以找到属于设计的分区键的文档吗?

2445.38 RU
显示结果
0 - 0
检索的文档计数:65671 检索的文档大小:294343656 字节
输出文档计数:0
输出文档大小:147 字节索引命中文档计数:0
索引查找时间:0 毫秒
文档加载时间:8804.060000000001 毫秒
查询引擎执行时间:133.11 ms
系统函数执行时间:0 ms
用户自定义函数执行时间:0 ms
文档写入时间:0 ms

标签: azureazure-cosmosdb

解决方案


我最终找到了问题的根源。为了搜索分区键,它需要被索引。考虑到分区键用于决定文档的存储位置,这让我觉得很奇怪,所以你会认为 Cosmos 天生就知道每个分区键的位置。

在索引项列表中包含分区键解决了我的问题。它还解释了为什么随着数据库大小的增加性能会随着时间的推移而下降——它正在扫描每一个文档。


推荐阅读