【问题标题】:How to optimize a query on a view with a computed field in MongoDB?如何使用 MongoDB 中的计算字段优化对视图的查询?
【发布时间】:2020-01-16 22:35:14
【问题描述】:

在 MongoDB 中,我有一个包含带有时间戳的文档的集合。我还对某些文档(按两个字段过滤)进行了汇总(按用户和月份分组)。该视图定义了一个复合索引:它由userId 和一个monthOfYear(带有月份的字符串YYYY-MM)组成。该视图还仅定义了两个字段:两者都是原始集合中某些字段的总和。

接下来我尝试在视图上运行查询,如果我尝试获取特定 userId 的视图的最后 13 个条目。

即使没有写入数据库(原始集合中的 50k 个文档需要 300 毫秒),这个查询的运行似乎也很慢。

我不明白应该创建什么样的索引来支持我的查询。如何优化它?

这是视图定义:

  {
    "name": "my_view",
    "type": "view",
    "options": {
      "viewOn": "my_collection",
      "pipeline": [
        {
          "$match": {
            "a": "val1",
            "b": "val2"
          }
        },
        {
          "$group": {
            "_id": {
              "userId": "$userId",
              "monthOfYear": {
                "$dateToString": {
                  "format": "%Y-%m",
                  "date": "$timestamp"
                }
              }
            },
            "total": {
              "$sum": "$val3"
            },
            "count": {
              "$sum": 1
            }
          }
        },
        {
          "$sort": {
            "_id.monthOfYear": -1
          }
        }
      ]
    },
    "info": {
      "readOnly": true
    }
  }

还有查询:

 {
    "find": "my_view",
    "filter": {
      "_id.userId": "000000000aaaa",
      "_id.monthOfYear":
        {
          "$gte":
            "2019-01"
        }
    },
    "lsid": {
      "id": UUID("aaa-bbb")
    },
    "$db":
      "my-db"
  }

谢谢!

【问题讨论】:

    标签: mongodb database-design query-optimization


    【解决方案1】:

    MongoDB 通过在读取操作期间按需执行聚合来计算视图内容。作为底层聚合管道的一部分,MongoDB 对视图执行读取操作。 https://docs.mongodb.com/manual/core/views/

    所以对my_view 执行查询,MongoDB 首先对my_collection 执行聚合,然后对返回的结果执行查询。

    尝试为my_collection 创建复合索引({a:1, b:1}) 以查看您的性能是否有所提高,但$group 会降低您的查询。

    其他解决方案是On-Demand Materialized Views。您执行聚合并使用$out or $merge 运算符将聚合数据存储在collection(假设my_collection2)中。现在,您为my_collection2 创建索引,您的查询将急剧增加。

    注意:每次更新my_collection,都需要更新my_collection2数据。

    【讨论】:

    • 谢谢,我会尽力回报的
    • 我已经在{a:1,b:1}{userId:1,timestamp:1} 上有了复合索引,但是后者与视图中的计算索引不同——timestamp 被转换为字符串YYYY-MM。我想,我需要尝试在文档中明确保存月份,然后直接在其上创建索引。
    猜你喜欢
    • 2015-10-28
    • 2022-12-08
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多