DocumentDB 每次在大型分页提取中返回不同的结果计数

DocumentDB returning different result count every time on large paged fetch

问题

我正在尝试从 docdb 中提取大约 20,000 个文档。为了减少我获取的数量,我只提取了文档的 ID。我正在翻阅结果,当我在完成后建立一个列表时,我发现结果的数量发生了变化(而且它们都是错误的!)。它没有得到它应该得到的所有结果。目前没有其他进程正在接触数据。

我的查询方式如下:

var sql = new SqlQuerySpec(@"SELECT items.id FROM items WHERE items.foo = @bar")
{
    Parameters = new SqlParameterCollection { new SqlParameter("@bar", bar) }
};

var feedOptions = new FeedOptions { MaxItemCount = 2000 };
var query = this.Context.Client.CreateDocumentQuery<Foo>(dbSelfLink, sql, feedOptions).AsDocumentQuery();

var ids = new List<string>();

while (query.HasMoreResults)
{
    var page = await query.ExecuteNextAsync<Foo>().ConfigureAwait(false);
    ids.AddRange(page.AsEnumerable());
}

我在调试时 运行 这三次,得到三个不同的 ID 计数:

19,323
19,321
19,327

其中 none 与我预期的一样高。它们与我的预期相差 100 左右。

我排除了什么

我所怀疑的

可能是我的速率受到限制(我的两个 collections 是 S2),但我不确定为什么这会改变结果的数量,或者我将如何证明这一点。我可能会尝试将 collections 升级到 S3 以查看是否可以解决问题,但这对我来说不起作用 long-term.

除此之外,我非常感谢任何对可能发生的事情的洞察。谢谢!

编辑

我尝试升级 collections。没有变化。

编辑 2 回复评论

是的,我们正在使用惰性索引...我开始怀疑这是否是罪魁祸首,但不确定为什么这会导致无法获取我们的所有记录。如果这需要改变,那可能没关系,因为索引最初是在没有考虑太多的情况下完成的(并且它使用的是旧格式,您可以在此处看到)。以下是索引策略:

{
  "indexingMode": "Lazy",
  "automatic": true,
  "includedPaths": [
    {
      "path": "/",
      "indexes": [
        {
          "kind": "Hash",
          "dataType": "Number",
          "precision": 3
        },
        {
          "kind": "Hash",
          "dataType": "String",
          "precision": 3
        }
      ]
    },
    {
      "path": "/\"_ts\"/?",
      "indexes": [
        {
          "kind": "Range",
          "dataType": "Number",
          "precision": 6
        },
        {
          "kind": "Hash",
          "dataType": "String",
          "precision": 3
        }
      ]
    }
  ],
  "excludedPaths": []
}

关于 MaxItemCount,我也尝试过使用 -1 并看到了类似的行为。

这是因为您使用的是惰性索引模式。顾名思义,惰性索引作为相对于写入的低优先级进程执行,并为查询提供 "eventually consistent results" 服务。

由于 DocumentDB 维护每个集合的多个副本(为了 HA 和性能),您的副本可能在为哪些文档编制索引方面领先或落后。

因为查询中的每个页面请求都由 client/gateway 为 load-balancing 随机路由,您可以看到 contain/miss 基于选择副本的结果。最终,当所有副本的索引都是最新的时,查询将 return 相同数量的结果。

如果您想要一致的查询结果,可以将集合切换为使用一致的索引模式。