我遇到了与文档数据库相关的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),我希望这个查询能够快速执行,因为没有实际返回的结果 . 但是,我可以看到它正在击中许多文档(即使它没有返回它们),我认为这可能是因为它没有使用查询的索引:
有趣的是,如果我将查询的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);
我最初的想法是这可能是由于缺少索引 . 我检查了我的索引设置,看起来所有的属性都应该编入索引,并且数字应该用适当的Range类型编入索引(而不是会导致订单问题的Hash类型) . 同样有趣的是,我认为大于比较(m.TimeStamp> syncToken)也会在_ts字段上使用范围索引,因此看起来有一个范围索引适用于_ts属性,但仅适用于>或<比较但不是OrderBY(这似乎很奇怪) .
所以,我的问题是:我如何调整索引以包含_ts属性,以便我的OrderBy查询能够使用索引而不是扫描?