MongoDB聚合查询性能提升
Posted
技术标签:
【中文标题】MongoDB聚合查询性能提升【英文标题】:MongoDB aggregate query performance improvement 【发布时间】:2020-01-10 11:55:28 【问题描述】:我最近开始将数据从 Microsoft SQL Server 转移到 MongoDB 以获得可扩展性。就移民而言,一切都很好。
该文档有 2 个重要字段:客户、timestamphash(年月日)。
我们在安装 MongoDB 的 Azure Linux 中仅导入了 7500 万个数据。 在两个字段上添加复合索引后,我们遇到了以下问题:
在 300 万条数据上(过滤后),按 customerId 计数完成一个聚合组需要 24 秒。对于相同的数据,SQL Server 在不到 1 秒的时间内给出结果。
您认为 Casandra 会是一个更好的解决方案吗?我们需要对大量数据的查询性能。
我尝试了磁盘写入,为 VM 提供了更多 RAM。没有任何效果。
查询:
aaggregate([
"$match" : "Customer" : 2 ,
"$match" : "TimestampHash" : "$gte" : 20160710 ,
"$match" : "TimestampHash" : "$lte" : 20190909 ,
"$group" : "_id" : "Device" : "$Device" , "__agg0" : "$sum" : 1 ,
"$project" : "Device" : "$_id.Device", "Count" : "$__agg0", "_id" : 0 ,
"$skip" : 0 ,
"$limit" : 10 ])
更新: 我使用了“allowDiskUse:true”,问题就解决了。过滤 3M 数据的时间缩短至 4 秒。
【问题讨论】:
“在两个字段上添加索引后”——您是在两个字段上创建复合索引还是两个单独的索引?您能否分享您创建的确切索引和您尝试支持的查询模式? 我在两个字段上都创建了一个复合索引,并通过说明使用了该索引进行了测试。 谢谢!复合索引的顺序是什么?客户至上,对吧?该聚合是您正在运行的主要查询吗?您可以考虑添加 Device 以使其成为覆盖查询 在 mongo 文档中,group by 语句不使用索引。我用 allowDiskUse:true 解决了这个问题。 【参考方案1】:我遇到过similar problem before, during this question,老实说,我猜你的某些情况下 Cassandra 更好,但问题是关于 Mongo 聚合查询优化,对吧?
就目前而言,我的一个集合拥有超过 300 万个文档,如果您正确构建索引,聚合查询不应花费 24 秒。
-
首先,通过 Mongo Compass 查看索引使用情况。 Mongo真的在使用它吗?如果您的应用程序
spam
查询 DB 并且您的 index
使用率为 0(如下例所示),那么正如您已经猜到的那样,您的索引有问题。
第二件事是,使用explain
方法(this doc will help you out)查看更多关于您的query
的信息。
第三点:索引字段排序很重要。例如,如果您有 3 个字段的 $match
阶段并且您按字段请求文档:
$match: a_field:a, b_field:b, c_field:c
那么您应该以完全相同的顺序在 a、b、c 字段上构建 compound
索引。
总是存在某种数据库架构问题。我强烈建议您不要stockpile
一个集合中的所有数据。在插入时使用timestamps:true
(它创建了两个字段,例如createdAt:
和updatedAt:
timestamps: true
在您的架构中,将过时/过时的数据存储在不同的集合中,并在您确实需要使用它们时为它们使用$lookup
aggregation method。
希望你能在我的回答中找到有用的东西。
【讨论】:
嗨,Alex,感谢您抽出宝贵时间。我用explain测试过,使用了索引,问题出在大数据上。在 70M+ 文档上,我将它们过滤为 3M+ 文档并在字段上应用分组,在投影阶段我根据该字段进行计数。 我找到了一个时间事件的解决方案,您可以将 1 个月的所有数据保存在一个文档中,但迁移会太难。只是想找到更好的解决方案。以上是关于MongoDB聚合查询性能提升的主要内容,如果未能解决你的问题,请参考以下文章
ClickHouse 使用物化字段投影 PROJECTION 提升性能