我遇到了与文档数据库相关的CosmosDB查询性能/索引问题(与图数据库相对) . 我正在使用C#和SDK的最新Nuget版本 . 我有一个似乎没有正确使用索引的查询,我无法弄清楚为什么 . 作为参考,这是被查询文档的结构:

internal class MeetingFeedLastChange
{
    public MeetingFeedLastChange() { }

    [JsonProperty(PropertyName = "partitionKey")]
    public string UserId { get; set; }

    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    [JsonProperty(PropertyName = "meetingId")]
    public string MeetingId { get; set; }

    [JsonProperty(PropertyName = "_etag")]
    public string ETag { get; set; }

    [JsonProperty(PropertyName = "createDate")]
    [JsonConverter(typeof(UTCDateTimeOffsetConverter))]
    public DateTimeOffset CreateDate { get; set; }

    [JsonProperty(PropertyName = "_ts")]
    public Int64 TimeStamp { get; set; }

    [JsonProperty(PropertyName = "documentType")]
    public DocumentType DocumentType { get { return DocumentType.MeetingFeedLastChange; } }
}

这是我正在执行的查询:

var documents = await QueryAsync(client.CreateDocumentQuery<MeetingFeedLastChange>(MessagingCollectionUri, queryOptions)
                    .Where(m => m.UserId == userId && m.DocumentType == DocumentType.MeetingFeedLastChange && m.TimeStamp > syncToken)
                    .OrderBy(m => m.TimeStamp), null);

QueryAsync方法只执行查询并执行一些性能日志记录 . 请注意,我使用系统生成的_ts字段来确定自上次执行此查询以来是否有任何文档已更改 . 这是将delta更改同步到客户端的一种非常方便的方法 . 此查询执行得相当频繁,我最近开始获取数据库限制警报 . 我的日志记录表明此查询的成本比类似查询多10倍RU / s . 如果我将QueryOptions.PopulateQueryMetrics设置为true并传入一个非常大的syncToken值(如long.MaxValue),我希望这个查询能够快速执行,因为没有实际返回的结果 . 但是,我可以看到它正在击中许多文档(即使它没有返回它们),我认为这可能是因为它没有使用查询的索引:

enter image description here

有趣的是,如果我将查询的OrderBy部分更改为任何其他属性(字符串,数字或日期),或者完全删除它,则使用索引并获得更期望的结果:

var documents = await QueryAsync(client.CreateDocumentQuery<MeetingFeedLastChange>(MessagingCollectionUri, queryOptions)
                    .Where(m => m.UserId == userId && m.DocumentType == DocumentType.MeetingFeedLastChange && m.TimeStamp > syncToken)
                    .OrderBy(m => m.DocumentType), null);

enter image description here

我最初的想法是这可能是由于缺少索引 . 我检查了我的索引设置,看起来所有的属性都应该编入索引,并且数字应该用适当的Range类型编入索引(而不是会导致订单问题的Hash类型) . 同样有趣的是,我认为大于比较(m.TimeStamp> syncToken)也会在_ts字段上使用范围索引,因此看起来有一个范围索引适用于_ts属性,但仅适用于>或<比较但不是OrderBY(这似乎很奇怪) .

enter image description here

所以,我的问题是:我如何调整索引以包含_ts属性,以便我的OrderBy查询能够使用索引而不是扫描?