Azure Cosmos数据库聚合和索引

时间:2018-04-09 17:35:39

标签: azure-cosmosdb

我试图使用Cosmos数据库,而且我在集合中进行简单计数时遇到了一些麻烦。

我的收藏架构如下,我在这个收藏中有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文档中,我发现了这个cenario,建议增加RU。目前我有400 RU / s,当我增加到10.000 RU / s时,我能够在没有错误的情况下运行命令,但是在5秒内。

我已经尝试创建索引显式,但似乎Cosmos DB没有使用索引进行计数。

我不认为在一个包含大约100,000个文档的集合中为简单计数支付10,000 RU / s是不合理的,尽管大约需要5秒钟。

2 个答案:

答案 0 :(得分:1)

按筛选器查询计数使用索引(如果可用)。

如果您尝试按非索引列上的过滤器计数,则查询不会超时,但会失败。试试吧。你应该得到错误:

  

{“错误”:[“指定了无效的查询,其中包含针对从索引中排除的路径的过滤器。请考虑在请求中添加允许扫描标头。”]}

所以一定要在UserID添加合适的索引。

如果您没有索引覆盖并且没有收到上述错误,那么您可能已设置 enableScanInQuery 标记。这几乎总是一个坏主意,全扫描不会扩展。含义 - 随着数据集的增长,它将消耗越来越多的RU。所以确保它关闭并改为索引。

如果您在所选列上有索引,则应运行查询。您可以通过发送x-ms-documentdb-populatequerymetrics标头验证索引实际正在使用。哪个应该返回indexLookupTimeInMsindexUtilizationRatio字段的确认信息。示例输出:

  

“totalExecutionTimeInMs = 8.44; queryCompileTimeInMs = 8.01; queryLogicalPlanBuildTimeInMs = 0.04; queryPhysicalPlanBuildTimeInMs = 0.06; queryOptimizationTimeInMs = 0.00; VMExecutionTimeInMs = 0.14;的 indexLookupTimeInMs = 0.11 ; documentLoadTimeInMs = 0.00; systemFunctionExecuteTimeInMs = 0.00; userFunctionExecuteTimeInMs = 0.00 ; retrievedDocumentCount = 0; retrievedDocumentSize = 0; outputDocumentCount = 1; outputDocumentSize = 0; writeOutputTimeInMs = 0.01;的 indexUtilizationRatio = 0.00

如果您觉得RU费用太大,它还可以为您提供一些见解。

如果索引查找时间本身太高,请考虑索引是否足够有选择性以及索引设置是否合适。查看您的UserId值和分布,并相应地调整索引。

要考虑的另一个猜测是检查您使用的API是否会推迟执行find(..) ,直到它知道count()确实是您所追求的。目前还不清楚您正在使用哪种API。如果事实证明它在进行计数之前将所有匹配的文档提取到客户端那么这将解释意外的高RU成本,特别是如果涉及大量匹配文档或大文档。 查看API文档

我还建议直接在Azure门户中执行相同的查询以比较RU成本,并验证问题是否与客户端相关。

答案 1 :(得分:0)

我认为这是行不通的。

在选择要计数的文档时似乎使用了索引,但是随后通过读取每个文档来完成计数,因此有效地消耗了很多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。请注意状态:“我们已经开始使用此功能。当此功能普遍可用时,将在此处更新。”

说实话,这真令人失望,尤其是因为这个限制已经有近两年没有得到解决了。注意-我不是这方面的专家,我很想被证明是错误的,因为我也需要此功能。

顺便说一句:我注意到似乎为每个单独的字段自动创建了简单的索引,因此不需要手动创建它们。