Как оптимизировать запрос для представления с вычисляемым полем в MongoDB? - PullRequest
0 голосов
/ 17 января 2020

В MongoDB у меня есть коллекция, в которой хранятся документы с отметкой времени. У меня также есть представление о некоторых документах (отфильтрованных по двум полям), в которых эти документы агрегированы (сгруппированы по пользователям и месяцам). Представление определяет составной индекс: он состоит из userId и monthOfYear (строка с месяцем YYYY-MM). Представление дополнительно определяет только два поля: оба являются суммами некоторых полей из исходной коллекции.

Далее я пытаюсь выполнить запросы к представлению, в котором я пытаюсь получить последние 13 записей представления для указанного c userId.

Похоже, этот запрос выполняется довольно медленно даже когда нет записи в БД (300 мс для 50k документов в оригинальной коллекции).

Я не понимаю, какие индексы мне следует создать для поддержки моего запроса. Как я могу его оптимизировать?

Вот определение вида:

  {
    "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"
  }

Спасибо!

1 Ответ

0 голосов
/ 17 января 2020

MongoDB вычисляет содержимое представления, выполняя агрегирование по требованию во время операций чтения. MongoDB выполняет операции чтения для представлений как часть базового конвейера агрегации. https://docs.mongodb.com/manual/core/views/

Таким образом, выполняя запрос для my_view, MongoDB fist выполняет агрегирование по my_collection, а затем выполняет ваш запрос по возвращенным результатам.

Попробуйте создать составной индекс ({a:1, b:1}) для my_collection, чтобы увидеть, улучшается ли ваша производительность, но $group уменьшает ваш запрос.

Другое решение - Материализованные представления по требованию . Вы выполняете агрегирование и используете операторы $ out или $ merge для хранения агрегированных данных в collection (скажем, my_collection2). Теперь вы создаете индексы для my_collection2, и ваши запросы резко возрастут.

Примечание: Каждый раз, когда вы обновляете my_collection, вам необходимо обновить my_collection2 данные.

...