Azure cosmosdb 具有偏移量和限制的Cosmos DB分页性能

Azure cosmosdb 具有偏移量和限制的Cosmos DB分页性能,azure-cosmosdb,Azure Cosmosdb,我正在创建一个基于Cosmos DB和ASP.NET Core 3.0的API。使用Cosmos DB 4.0预览版1.NET核心SDK。我使用OFFSET和LIMIT子句实现了分页。我看到RU费用随着页面数的增加而显著增加。页面大小为100个项目的示例: Page 1: 9.78 RU Page 10: 37.28 RU Page 100: 312.22 RU Page 500: 358.68 RU 这些问题很简单: 选择*从c偏移量[页面*大小]限制[大小] 是我做错了什么,还是这是意料之

我正在创建一个基于Cosmos DB和ASP.NET Core 3.0的API。使用Cosmos DB 4.0预览版1.NET核心SDK。我使用OFFSET和LIMIT子句实现了分页。我看到RU费用随着页面数的增加而显著增加。页面大小为100个项目的示例:

Page 1: 9.78 RU
Page 10: 37.28 RU
Page 100: 312.22 RU
Page 500: 358.68 RU
这些问题很简单:

选择*从c偏移量[页面*大小]限制[大小]

是我做错了什么,还是这是意料之中的?偏移量是否需要扫描整个逻辑分区?我正在查询一个分区键,该分区中有大约10000个项。分区中的项目越多,性能越差。(有关此功能,请参见中“Russ”的注释)

有没有更好的方法实现整个分区的高效分页

编辑1:另外,我注意到在Cosmos Emulator中执行查询时,在包含10000项的分区中执行偏移/限制时也会减慢waaayyy的速度

编辑2:这是我的查询存储库代码。本质上,它是包装Container.GetItemQueryStreamIterator()方法,并在处理IAsyncEnumerable时拉出RU。查询本身就是上面的SQL字符串,没有LINQ或其他神秘之处

public async Task<RepositoryPageResult<T>> GetPageAsync(int? page, int? pageSize, EntityFilters filters){

// Enforce default page and size if null
int validatedPage = GetValidatedPageNumber(page);
int validatedPageSize = GetValidatedPageSize(pageSize);

IAsyncEnumerable<Response> responseSet = cosmosService.Container.GetItemQueryStreamIterator(
    BuildQuery(validatedPage, validatedPageSize, filters),
    requestOptions: new QueryRequestOptions()
    {
        PartitionKey = new PartitionKey(ResolvePartitionKey())
    });

var pageResult = new RepositoryPageResult<T>(validatedPage, validatedPageSize);
await foreach (Response response in responseSet)
{
    LogResponse(response, COSMOS_REQUEST_TYPE_QUERY_ITEMS); // Read RU charge
    if (response.Status == STATUS_OK && response.ContentStream != null)
    {
        CosmosItemStreamQueryResultSet<T> responseContent = await response.ContentStream.FromJsonStreamAsync<CosmosItemStreamQueryResultSet<T>>();
        pageResult.Entities.AddRange(responseContent.Documents);
        foreach (var item in responseContent.Documents)
        {
            cache.Set(item.Id, item); // Add each item to cache
        }
    }
    else
    {
        // Unexpected status. Abort processing.
        return new RepositoryPageResult<T>(false, response.Status, message: "Unexpected response received while processing query response.");
    }
}

pageResult.Succeeded = true;
pageResult.StatusCode = STATUS_OK;
return pageResult;
事实上,检查浏览器中的“网络”选项卡会显示100个单独的HTTP查询,每个查询检索100个文档!因此,偏移量目前似乎不在数据库中,而是在客户端,客户端在丢弃前99个查询值的数据之前检索所有内容。这不可能是预期的设计吗?查询不是应该告诉数据库在一次响应中只返回100个项目,而不是全部返回10000个项目,这样客户机就可以扔掉9900个项目吗?

基于此,这意味着客户机跳过了文档,从而增加了RU

我在浏览器(cosmos.azure.com,使用JSSDK)上测试了相同的场景,行为是相同的,随着偏移量的移动,RU增加


它记录在官方文件的备注下

具有偏移限制的查询的RU费用将随着被偏移的术语数量的增加而增加。对于具有多页结果的查询,我们通常建议使用延续标记。延续标记是一个“书签”,用于查询稍后可以继续的位置。如果使用偏移限制,则没有“书签”。如果要返回查询的下一页,则必须从头开始


您能展示一下您是如何进行查询并获取这些RU值的吗?@MatiasQuaranta当然,我已经用存储库代码更新了问题。@MatiasQuaranta请参阅“编辑3”,似乎是客户端在跳过,而不是数据库。难道数据库不应该返回限制数量,而不是全部吗?谢谢。你知道这是否有文件记录吗?Cosmos是否有一种高效的方式来翻页浏览大量项目,或者有任何有帮助的自定义索引?您可以按照以下要求使用延续标记:
OFFSET 0 LIMIT 100: Output document count = 100, Output document size = 44 KB
OFFSET 9900 LIMIT 100: Output document count = 10000, Output document size = 4.4 MB