首页 > 解决方案 > 使用某些条目中缺少的管道和字段时,Mongo 查找非常慢

问题描述

下面的查询非常快

[{
    $match: {
        "deleted": {"$ne": true},
        "userId": {$exists: false}
    }
}, {
    $limit: 300
}, {
    $lookup: {
        from: 'users',
        localField: 'userId',
        foreignField: '_id',
        as: 'user'
    }
}, {
    $count: 'count'
}]

但是这个很慢,在我的情况下,我明白了

$cursor 阶段 :: 错误由 :: 操作超过时间限制引起

300,但适用于少数人

[
  {$match: {
    "deleted": {"$ne": true},
    "userId": {$exists: false}
  }}, 
  {$limit: 300}, 
  {$lookup: {
  "from": "users",
  "let": {
    "userId": "$userId"
  },
  "pipeline": [{
    "$match": {
      "$expr": {
        "$eq": ["$_id", "$$userId"]
      }
    },
  }],
  "as": "user"
  }}, 
  {$count: 'count'}
]

我使用 "userId": {$exists: false} 只是为了证明 userId 在大多数情况下通常存在多慢,但有时它不存在,并且对于可能为 50% 的情况,查询非常慢。

我已经尝试过稀疏索引并且我在 mongo 4.2 上。不确定,但这在最新的 mongo 上可能不会那么慢。

关于如何提高查询速度的任何想法?

谢谢

注意:这不是完整的查询,我有另一个联接和一些项目,否则我会使用第一个版本。

标签: mongodb

解决方案


在这个查询中,至少我看到了 2 个问题

  • 如果您有一个索引,请"userId"确保所有文档都有一个userId值,添加null, 以启用索引的使用(据我所知,检查缺少的字段 => collscan)
  • 在 MongoDB < 5 中,使用时不能在$lookupwith 管道内使用索引$expr(如果要与变量进行比较,则无法避免)

要修复它,如果可能的话,试试那些

  • 添加空值而不是缺少的字段(如果您在 userId 上有索引)
  • 更改为简单$lookup(并在查找后进行更改)或更新到 MongoDB 5

检查这个也这个


推荐阅读