Mongodb Агрегация медленный счет с использованием фасета - PullRequest
0 голосов
/ 10 января 2019

Я хочу использовать фасет для создания простого запроса, который я могу использовать для получения выгружаемых данных, однако я заметил, что если я это сделаю, то получаю очень низкую производительность по сравнению с выполнением всего двух отдельных запросов.

В качестве быстрого теста я создал коллекцию из 50000 случайных документов и выполнил следующий тест.

var x = new Date();
var a = {
count : db.getCollection("test").find({}).count(),
data: db.getCollection("test").find({}).skip(0).limit(10)
};

var y = new Date();
print('result ' + a);
print(y - x);

var x = new Date();
var a = db.getCollection("test").aggregate(
    [
        { 
            "$match" : {

            }
        }, 
        {
         "$facet" : {
        "data": [
          {
            "$skip": 0
          },
          {
            "$limit": 10
          }
        ],
        "pageInfo": [
          {
            "$group": {
              "_id": null,
              "count": {
                "$sum": 1
              }
            }
          }
        ]       

         }
        }
    ]
)
var y = new Date();
print('result ' + a);
print(y - x);

Результатом этого является то, что два отдельных запроса один для поиска, другой для подсчета занимает около 2 миллисекунды против одного запроса агрегации, занимающего более 500 миллисекунд .

Почему агрегация такая медленная?

Обновление

Даже простой подсчет без фасета в агрегации медленен

var x = new Date();
var a = db.getCollection("test").find({}).count();
var y = new Date();
print('result ' + a);
print(y - x);

var x = new Date();
var a = db.getCollection("test").aggregate(
    [
        { "$count" : "count" }
    ]
)
var y = new Date();
print('result ' + a);
print(y - x);

В приведенном выше примере с моим набором тестовых данных агрегационный счет занимает 200 мс против метода подсчета, принимающего 2 мс .

Эта проблема распространяется на драйвер Mongodb NodeJs, где метод .Count () объявлен устаревшим и заменен методом countDocuments (), а внутри нового метода countDocuments () используется агрегация, а не метод count в найти, как и в моем примере выше, он имеет значительно худшую производительность до того момента, когда я продолжу использовать устаревший метод по сравнению с более новым методом countDocuments ().

1 Ответ

0 голосов
/ 11 января 2019

Конечно, это медленно. Метод count() просто возвращает размер курсора после того, как запрос применен (что не обязательно требует чтения всех документов, в зависимости от вашего запроса и индексов). Кроме того, с пустым запросом оптимизатор запросов знает, что все документы должны быть возвращены, и в основном должен возвращать length(_id_1).

Агрегации по определению не работают таким образом. Если только этап сопоставления фактически не исключает документ, каждый документ считывается с «диска» (собственный кэш MongoDB и кэш FS в данный момент в стороне) для дальнейшей обработки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...