我们的cosmos db聚合查询似乎很慢,并且花费了很多RU。这是详细信息(另请参见下面的屏幕截图):2.4s和3222RUs用于计数414k记录的结果集。而且这只是一个计数。通常,我们希望一次对多个字段求和(只能在单个分区内),但是这样做的性能要差得多。
此收藏集中有200万条记录。我们正在使用带有SQL API的Cosmos DB。该特定集合按country_code划分,在法国(“ FR”)中有414,732条记录,在美国有其余记录。文档大小平均为917字节,也许最小为800字节,最大为1300字节。
请注意,我们还尝试了更稀疏的分区键,例如device_id(此处有200万个,每个设备1个文档),此查询的结果较差。 c.calcuated.flag1字段仅表示我们要保留的“状态”(实际上,我想总结一下8个状态)。
此集合的索引是默认的,它使用“一致”索引模式,并索引所有字段(并包括Number和String的范围索引)。 RU设置为20,000,并且数据库上没有其他活动。
所以,让我知道您对此的想法。可以在不增加我们的RU费用和花费很长时间的情况下,合理地使用Cosmos DB来获取字段的总数或计数吗?尽管2.4s并不糟糕,但我们确实需要亚秒级的查询来进行此类操作。我们的应用程序(基于IoT)通常需要单个文档,但有时也需要在一个国家/地区的所有文档中进行此类计数。
是否有提高性能的方法?
答案 0 :(得分:0)
对于显示的特定查询,无需指定表名称,并且您可以尝试限制1 ,某些性能将得到改善。例如:
SELECT COUNT(1) FROM c WHERE country_code="FR" AND calculated.flag=1 LIMIT 1
此外,我不确定在Cosmos中仔细分析您的查询执行情况,但是不确定,就像PostreSQL方法EXPLAIN ANALYSE
。另外,请确保使用的是最佳类型的变量,例如,varchar(2)而不是varchar(3)。如果要过滤它们(如您指出的那样),我建议按数字更改国家/地区的字符类型。例如,FR = 1,GR = 2,依此类推。这也将提高性能。最后,如果国家代码和计算出的标记相关,则创建一个定义它们的唯一变量。如果这些都不起作用,请检查客户端性能,甚至检查硬件。
答案 1 :(得分:0)
两个想法:
尝试运行以下命令,看看运行时间是否不同:
SELECT COUNT(1) FROM c WHERE country_code="FR"
重要! calculated.flag1
字段(如果不是持久性的)可能会引起问题-对于每个文档/记录,数据库引擎必须计算结果,因此RU。
您可以优化计算的字段吗? (将其分解,还是将计算作为查询的一部分?)
第二个建议是尝试使您定义一个复合索引
{
"automatic":true,
"indexingMode":"Consistent",
"includedPaths":[
{
"path":"/*"
}
],
"excludedPaths":[
],
"compositeIndexes":[
[
{
"path":"/country_code",
"order":"ascending"
},
{
"path":"/calculated",
"order":"descending"
}
]
]
}
另请参阅Composite indexing policy examples
然后Manage indexing policies in Azure Cosmos DB查看您在哪里进行编辑
答案 2 :(得分:0)
Cosmos DB团队现在对聚合性能以及如何使用索引进行了一些重大更改。这是他们的索引“ v2”策略,并且仅在最近才推出(它可能不适用于所有帐户,如果您有需要升级的旧数据库,请与MSFT联系。)
您可以将新结果与我最初发布的图片进行比较。
您现在将注意到,文档加载时间显示为0ms,检索到的文档大小为0字节。我可以确认的加载时间现在确实非常快,因此从服务器端进行测量时,加载时间可能小于1毫秒。而且文件大小为0更有意义,因为不需要为此检索任何文件(仅根据索引进行计数)。
最后您可以看到RU从3222下降到7.4 !!!!很大的不同。
在一个分区中一次对多个列进行求和现在也很有效,我们可以在200个文档中一次执行约8次求和,具有〜50 RU,并且从函数API端点进行测量大约需要20-70毫秒(因此包括网络时间。
Cosmos DB团队仍然需要做更多的工作来允许跨分区的多列聚合,但是我们现在的改进是很有希望的。