为什么这个零结果 Cosmos DB 查询如此昂贵?
Why is this zero result Cosmos DB query so expensive?
我正在调查为什么我们在 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 使用 4730RU - 对于相同的无结果查询,多出 40 倍以上。
添加更多细节:一致性设置为一致的前缀。是单一区域。
另一个更新:
我已经复制了通过 Azure 门户查询的问题,它与容器中的记录数有关。查看查询统计信息,就好像它正在加载容器中的每个文档以搜索分区键。分区键不是最高效的搜索方式吗? Cosmos 是否不知道在设计时确切地知道在哪里可以找到属于分区键的文档?
2445.38 RU
显示结果
0 - 0
检索到的文档数:65671
检索到的文档大小:294343656 字节
输出文档数:0
输出文档大小:147 字节
索引命中文档数:0
索引查找时间:0 毫秒
文档加载时间:8804.060000000001 毫秒
查询引擎执行时间:133.11 毫秒
系统函数执行时间:0 ms
用户自定义函数执行时间:0 ms
文档写入时间:0 毫秒
我终于找到了问题的根源。为了搜索分区键,需要对其进行索引。考虑到分区键用于决定文档的存储位置,这让我觉得很奇怪,所以你会认为 Cosmos 本身就知道每个分区键的位置。
在索引项列表中包含分区键解决了我的问题。它还解释了为什么随着数据库大小的增加性能会随着时间的推移而下降 - 它正在扫描每个文档。
我正在调查为什么我们在 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 使用 4730RU - 对于相同的无结果查询,多出 40 倍以上。
添加更多细节:一致性设置为一致的前缀。是单一区域。
另一个更新:
我已经复制了通过 Azure 门户查询的问题,它与容器中的记录数有关。查看查询统计信息,就好像它正在加载容器中的每个文档以搜索分区键。分区键不是最高效的搜索方式吗? Cosmos 是否不知道在设计时确切地知道在哪里可以找到属于分区键的文档?
2445.38 RU
显示结果
0 - 0
检索到的文档数:65671
检索到的文档大小:294343656 字节
输出文档数:0
输出文档大小:147 字节
索引命中文档数:0
索引查找时间:0 毫秒
文档加载时间:8804.060000000001 毫秒
查询引擎执行时间:133.11 毫秒
系统函数执行时间:0 ms
用户自定义函数执行时间:0 ms
文档写入时间:0 毫秒
我终于找到了问题的根源。为了搜索分区键,需要对其进行索引。考虑到分区键用于决定文档的存储位置,这让我觉得很奇怪,所以你会认为 Cosmos 本身就知道每个分区键的位置。
在索引项列表中包含分区键解决了我的问题。它还解释了为什么随着数据库大小的增加性能会随着时间的推移而下降 - 它正在扫描每个文档。