我正在尝试使用Cosmos DB,但在集合中进行简单计数时遇到了一些问题。
我的集合模式如下,我在这个集合中有80.000个文档。
{
"_id" : ObjectId("5aca8ea670ed86102488d39d"),
"UserID" : "5ac161d742092040783a4ee1",
"ReferenceID" : 87396,
"ReferenceDate" : ISODate("2018-04-08T21:50:30.167Z"),
"ElapsedTime" : 1694,
"CreatedDate" : ISODate("2018-04-08T21:50:30.168Z")
}
如果我运行以下命令来计算集合中的所有文档,我很快就会得到结果:
db.Tests.count()
但是当我对一个特定的用户运行同样的命令时,我得到一条消息“请求率很大”。
db.Tests.find({UserID:"5ac161d742092040783a4ee1"}).count()
在Cosmos DB文档中,我发现了这个场景,并且建议增加RU。目前我的速度是400 RU/s,当我提高到10.000 RU/s时,我能够在5秒内运行命令而不出错。
我已经尝试创建索引显式,但似乎 Cosmos DB 不使用索引进行计数。
我认为在大约100,000份文件的集合中支付10,000 RU/s的简单计数是不合理的,尽管大约需要5秒钟。
我认为它就是行不通。
索引似乎是在选择要计数的文档时使用的,但是计数是通过读取每个文档来完成的,因此实际上消耗了大量的RU。
此查询既便宜又快速:
db.Tests.count({ UserID: { '$eq': '5ac161d742092040783a4ee1' }})
但是这个又慢又贵:
db.Tests.count({ ReferenceID: { '$gt': 10 }})
尽管这个查询很快:
db.Tests.find({ ReferenceID: { '$gt': 10 }}).sort({ ReferenceID: 1 })
我也发现了这一点:https://feedback.azure.com/forums/263030-azure-cosmos-db/suggestions/36142468-make-count-aware-of-indexes。请注意状态:“我们已开始开发此功能。当它正式发布时,将在此处更新。
说实话,非常令人失望,特别是因为这个限制已经将近2年没有得到解决。注意 - 我不是这方面的专家,我很想被证明是错误的,因为我也需要这个功能。
顺便说一句:我注意到简单的索引似乎是为每个单独的字段自动创建的,因此无需手动创建它们。
按筛选器计数查询正在使用索引(如果可用)。
如果在未索引列上尝试按筛选器计数,则查询不会超时,但会失败。试试看。您应该得到如下错误:
{"Errors":["针对从索引中排除的路径使用筛选器指定了无效查询。请考虑在请求中添加允许扫描标头。]}
所以一定要在< code>UserID上添加一个合适的索引。
如果您没有索引覆盖并且没有得到上面的错误,那么您可能已经设置了enableScanInQuery标志。这几乎总是一个坏主意,全扫描将不会缩放。这意味着,随着数据集的增长,它将消耗越来越多的RU。因此,请确保它是关闭的,而不是索引。
如果所选列上有索引,则应运行查询。您可以通过发送 x-ms-documentdb-填充查询标头来验证索引是否实际被使用。这应该返回您与索引查找时间InMs
和索引利用率Ratio字段的
确认。输出示例:
“总执行时间InMs=8.44;查询编译时间InMs=8.01;queryLogicalPlanBuildTimeInMs=0.04;query物理计划生成时间InMs=0.06;query优化时间InMs=0.00;VMExecutionTimeInMs=0.14;indexLookupTimeInMs=0.11;documentLoadTimeInMs=0.00;systemFunctionExecuteTimeInMs=0.00;userFunctionExecuteTimeInMs=0.00;检索文档计数=0;检索文档大小=0;outputDocumentCount=1;outputDocumentSize=0;writeOutputTimeInMs=0.01;indexUtilizationRatio=0.00”
它还为您提供了一些见解,如果您觉得RU费用太大,那么工作量已经发展到哪里。
如果索引查找时间本身太高,请考虑您的索引是否足够有选择性以及索引设置是否合适。查看您的UserId
值和分布,并相应地调整索引。
另一个需要考虑的猜测是,检查您使用的API是否会延迟执行<code>find(…)是您真正想要的。不清楚您使用的是哪种API。如果在进行计数之前将所有匹配文档提取到客户端,那么这将解释RU成本异常高的原因,尤其是当涉及大量匹配文档或大型文档时。查看API文档。
我还建议直接在Azure Portal中执行相同的查询,以比较RU成本并验证问题是否与客户端相关。