【问题标题】:Mongo DB like search with count is very slow on 50 million collection dataMongodb like search with count 在 5000 万个集合数据上非常慢
【发布时间】:2022-01-28 02:31:41
【问题描述】:

在我的应用程序中,我收集了 5000 万条数据。我正在使用类似搜索,然后计算特定字段(即 Patientfirstname)的结果。我还在 Patientfirstname 字段上创建了一个索引,它提高了性能,但仍然需要很多时间。

db.patients.find({"Patientfirstname":{"$regex":"Testuser"}}).count() 无索引 40

db.patients.find({"Patientfirstname":{"$regex":"Testuser"}}).count() 在 Patientfirstname 字段上添加索引后 31

db.patients.find({"Patientfirstname":{"$regex":"Testuser"}}).count()

我尝试了不同的方法(聚合),但响应仍然很慢

 db.patients.aggregate.([{$match:{"Patientfirstname":{"$regex":"Testuser"}}},
{$project:{"Patientfirstname":1,"_id":1}},
{$group : {_id:"$Patientfirstname", count:{$sum:1}}},
{$sort:{"count":-1}} ])

这个查询也需要同样的时间来获取结果 31 秒

尝试了另一种方法,但结果不正确

仅从整个集合中选择字段,然后像搜索、计数和结果一样应用。

db.patients.find({},{Patientfirstname:1,_id:1}).count({"Patientfirstname":{"$regex":"Testuser"}})

在计数中应用过滤器不起作用,将显示整个集合计数 请在此查询中提供帮助以更快地获取结果。在此先感谢

【问题讨论】:

标签: node.js mongodb mongoose mongodb-query nosql


【解决方案1】:

所以这是交易:

正如在 cmets 中正确指出的那样,$regex 是一个无论有没有索引都不会表现良好的运算符。原因如下:

没有索引的查询很慢,因为它们使用 COLLSCAN 执行 - 这实际上是对磁盘上整个 5000 万个文档的逐一迭代,过滤数据并仅返回匹配的数据。磁盘本身就是一种速度较慢的硬件也无济于事。

现在,当被索引时 - MongoDB 在 RAM 中创建一个 B-Tree。并且 $regex 运算符本质上不是很有选择性,它强制在索引 b-tree 中进行完整的树扫描(与在相等或范围的情况下减少/部分树扫描相比) - 这与集合扫描本身一样糟糕.您在 9 秒内获得好处的唯一原因是此树扫描发生在 RAM 中,而不是磁盘中。

话虽如此,有几个替代方案:

  1. 优化您的 $regex。来自MongoDB Documentation 本身:

对于区分大小写的正则表达式查询,如果字段存在索引,则 MongoDB 会将正则表达式与索引中的值进行匹配,这可能比集合扫描更快。如果正则表达式是“前缀表达式”,则可以进行进一步优化,这意味着所有潜在匹配都以相同的字符串开头。这允许 MongoDB 从该前缀构造一个“范围”,并且只匹配索引中落在该范围内的那些值。

如果正则表达式以插入符号 (^) 或左锚 (\A) 开头,后跟一串简单符号,则它是“前缀表达式”。例如,正则表达式 /^abc.*/ 将通过仅匹配索引中以 abc 开头的值进行优化。

此外,虽然 /^a/、/^a./ 和 /^a.$/ 匹配等效字符串,但它们具有不同的性能特征。如果存在适当的索引,则所有这些表达式都使用索引;但是,/^a./ 和 /^a.$/ 速度较慢。 /^a/ 匹配前缀后可以停止扫描。

不区分大小写的正则表达式查询通常不能有效地使用索引。 $regex 实现不支持排序规则,无法使用不区分大小写的索引。

  1. 创建一个Text Index - 这将标记您的文本字符串并启用更快的基于文本的搜索

  2. 如果您部署在 MongoDB Atlas 上 - 那么您可以使用 Atlas Search,它是一个基于 Lucene 的文本搜索引擎(几乎像类固醇上的 elasticsearch)。这提供了更好的性能和功能,例如模糊文本搜索、文本自动完成等。

【讨论】:

    猜你喜欢
    • 2016-08-29
    • 2013-04-10
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 2020-10-05
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多