CosmosDb意外延续令牌

时间:2019-04-05 08:27:54

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

请注意:

  • 我相信这个问题与here所讨论的为什么延续令牌为空的问题有所不同。此处列出的问题是关于讨论此意外行为并查看是否有解决方案。
  • 我也在cosmosdb github issues上进行了报道,因为在现阶段我认为这很可能是SDK或Cosmos API错误。

在这里:

基本上,在意外情况下,使用延续令牌没有结果。

我对CosmosDb的唯一类似体验(无结果,只有延续令牌)是当RU不够且查询需要更多RU才能完成其工作时。例如,计算所有文档时,您需要继续几次。

如何重现此问题?

由于使用者无法控制分片(物理分区)的分布,因此很难复制。但是您需要一个具有几个逻辑分区和至少两个分片的comosdb,并且应该针对第二个共享中的数据形成查询。不要提供分区键并使查询成为跨分区。

预期的行为

何时:

  • 查询是交叉分区
  • 有足够的RU
  • 查询的费用非常小RU

我希望在第一个电话中收到结果。

实际行为

查询结果为空 响应具有异常的延续令牌 令牌如下所示:

  

{“令牌”:空,“范围”:{“最小”:“ 05C1DFFFFFFFFCFC”,“最大”:“ FF”}}

以下是示例代码,我可以每次重现此问题。在这种情况下,我有一个文档位于分区2(索引1)中,我认为它是第二个分片。

var client = new DocumentClient(ServiceEndpoint, AuthKey);
const string query = "select * from c where c.title='JACK CALLAGHAN'";
var collection = UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId);
var cQuery = client.CreateDocumentQuery<dynamic>(collection, query, new FeedOptions
{
    EnableCrossPartitionQuery = true,
    PopulateQueryMetrics = true
}).AsDocumentQuery();

var response = cQuery.ExecuteNextAsync().GetAwaiter().GetResult();

Console.WriteLine($"response.AsEnumerable().Count()= {response.AsEnumerable().Count()}");

foreach (string headerKey in response.ResponseHeaders.Keys)
{
    Console.WriteLine($"{headerKey}");
    var keyValues = response.ResponseHeaders[headerKey].Split(";");
    foreach (var keyValue in keyValues)
    {
        Console.WriteLine($"{keyValue}");
    }
    Console.WriteLine();
}

输出包括所有标题:

response.AsEnumerable().Count()= 0
Cache-Control
no-store, no-cache

Pragma
no-cache

Transfer-Encoding
chunked

Server
Microsoft-HTTPAPI/2.0

Strict-Transport-Security
max-age=31536000

x-ms-last-state-change-utc
Wed, 03 Apr 2019 00:50:35.469 GMT

x-ms-resource-quota
documentSize=51200
documentsSize=52428800
documentsCount=-1
collectionSize=52428800

x-ms-resource-usage
documentSize=184
documentsSize=164076
documentsCount=94186
collectionSize=188910

lsn
118852

x-ms-item-count
0

x-ms-schemaversion
1.7

x-ms-alt-content-path
dbs/bettingedge/colls/fixtures

x-ms-content-path
S8sXAPPiCdc=

x-ms-xp-role
1

x-ms-documentdb-query-metrics
totalExecutionTimeInMs=0.27
queryCompileTimeInMs=0.04
queryLogicalPlanBuildTimeInMs=0.02
queryPhysicalPlanBuildTimeInMs=0.03
queryOptimizationTimeInMs=0.00
VMExecutionTimeInMs=0.06
indexLookupTimeInMs=0.05
documentLoadTimeInMs=0.00
systemFunctionExecuteTimeInMs=0.00
userFunctionExecuteTimeInMs=0.00
retrievedDocumentCount=0
retrievedDocumentSize=0
outputDocumentCount=0
outputDocumentSize=49
writeOutputTimeInMs=0.00
indexUtilizationRatio=0.00

x-ms-global-Committed-lsn
118851

x-ms-number-of-read-regions
0

x-ms-transport-request-id
12

x-ms-cosmos-llsn
118852

x-ms-session-token
0:-1#118852

x-ms-request-charge
2.86

x-ms-serviceversion
version=2.2.0.0

x-ms-activity-id
c4bc4b76-47c2-42e9-868a-9ecfe0936b1e

x-ms-continuation
{"token":null,"range":{"min":"05C1DFFFFFFFFC","max":"FF"}}

x-ms-gatewayversion
version=2.2.0.0

Date
Fri, 05 Apr 2019 05:40:21 GMT

Content-Type
application/json

如果我们使用复合延续令牌继续查询,我们可以看到结果。

这是正常行为还是错误?

2 个答案:

答案 0 :(得分:0)

使用.NET Framework将本机处理延续令牌:

`var query = Client.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(databaseId,collectionI, sqlQuery,feedOptions).AsDocumentQuery();

同时(query.HasMoreResults)

{var response = await query.ExecuteNextAsync();              results.AddRange(response);}`

添加通过链接的GitHub Issue提供的反馈:

关于您的问题,我们也遇到过同样的情况。 我有一些评论。

  

我们对这种行为一无所知,我们的客户收到一个带有延续令牌的空列表,这几乎中断了我们的流程。

     

现在在服务器端,我们正在处理这种情况,并继续进行直到获得结果。问题是如果有1000个分区,该怎么办。我们必须继续100次吗?这就是ComosDB如何在10 ms的响应时间内保护其SLA。 $ ThinkingLoud

是的,这也第一次打破了我们的流程。但是我们也可以在服务器端处理它(与MaxNumberOfObjects一起,我们继续处理请求,直到我们收到客户端想要的数字为止),并且您看到的模式是由于CosmosDB的底层体系结构(由phyiscal +分区。听起来您是在与客户端的相互作用来实现分页,这很好。但是,我不认为这是CosmosDB在其SLA时间中所指的。

  

还有哪些其他未记录的意外行为会在生产环境中使我们感到惊讶? #ThinkingLoudAgain

这有点含糊,但是我的建议是让您阅读所有FeedOptions以及CosmosDB Performance技巧,并确保您了解它们以及它们的应用领域。

编辑:另外,另一个警告。我目前在SQL查询中遇到Continuation Token和DISTINCT关键字的问题。如果没有ORDER BY,则无法正常工作。

答案 1 :(得分:0)

这是 CosmosDb 的正常行为。有几种情况会导致查询在内部超时并导致响应很少甚至是空集合。

来自CosmosDb documentation

<块引用>

每次查询执行返回的项目数将始终小于或等于 MaxItemCount。但是,其他条件可能限制了查询可以返回的结果数。如果多次执行同一个查询,页数可能不是恒定的。例如,如果查询受到限制,每页的可用结果可能会减少,这意味着查询将有更多的页面。 在某些情况下,您的查询也可能返回空白页