用于收集超过 1000 万条记录的 Mongo 查询优化

Posted

技术标签:

【中文标题】用于收集超过 1000 万条记录的 Mongo 查询优化【英文标题】:Mongo Query Optimization for collection over 10 Million records 【发布时间】:2020-06-23 13:35:22 【问题描述】:

我有一个包含超过 1000 万条记录的集合,我需要匹配特定字段并获取 记录集的不同 _id。

在 $match 管道之后,结果集变得少于 500 万。 如果我用 id 分组来获取唯一的 id,我本地环境的执行时间超过 20 秒。

db.getCollection('viewscounts').aggregate(
[
   
       $match: 
           MODULE_ID: 4, 
       
   ,
   
       $group: 
           _id: '$ITEM_ID',
       
   
],  allowDiskUse: true )
如果我去掉 $match 或 $group 并且只有 1 个管道,则执行时间小于 0.1 秒。

我可以限制 _id,但它们应该是唯一的。

谁能提出更好的方法来更快地获得结果?

【问题讨论】:

你能解释一下变量和条件VIEWED_DATE: 3 === 3是什么以及它的用途吗? 嗨@hhharsha36 别担心,它是一个条件匹配,添加这种情况以进入真实路径以进行测试。我已经删除了整个声明。 【参考方案1】:

您已经为查询实现了最佳聚合管道以获得所需的输出。

仅使用一个聚合管道时查询结果更快的原因是查询结果返回部分输出而不是全部 500 万条记录。当您添加两个阶段时,$match 阶段的整个输出必须由$group 阶段处理,从而导致更多时间。

优化聚合查询的唯一方法是在 MODULE_IDITEM_ID 键上应用索引

db.viewscounts.createIndex(MODULE_ID: 1,  sparse: true )
db.viewscounts.createIndex(ITEM_ID: 1)

在您的viewscounts 集合上执行上述两个索引后应该会更快。

此外,您还可以从 MongoDB distinct 命令中获得所需的输出。试试下面的查询,看看是否有帮助。

db.getCollection('viewscounts').distinct("ITEM_ID", "MODULE_ID": 4)

注意:上面的查询返回一个唯一键值数组,而不是聚合查询中的对象

希望对你有帮助

【讨论】:

你知道除了普通聚合之外的任何其他方法来处理这个大型集合,例如:- 大数据方法或分片数据库。 除了distinct这个操作,我觉得没有别的办法了。作为菜鸟,我这里可能错了

以上是关于用于收集超过 1000 万条记录的 Mongo 查询优化的主要内容,如果未能解决你的问题,请参考以下文章

1000万条记录sql更新耗时4天

在没有并行提示和批量收集的情况下删除数百万条记录

Mysql - 超过 10m 数据的查询表

用于处理大量数据(100 万条记录及更多)的数据结构和技术

超过 500 万条记录的 MongoDB 查询性能

如何以超过 15 秒的速度对超过 300 万条记录的表进行此查询?