Как ускорить курсор $ gt в индексированном поле в MongoDB? - PullRequest
0 голосов
/ 08 мая 2020

Пример использования: Go для всей коллекции, отсортированной по ключу, для проведения вычислений. Поскольку время выполнения велико, мы запускаем его несколько раз, используя $gt на ключе.

Запрос Ниже приведена запись журнала от курсора по запросу, как показано ниже :

{ mpn_alnum: { "$gt" : "ABCD" } }

Вывод журнала

Отформатировано для удобства чтения при переполнении стека:

command iodparts.searches command: 
  getMore {
    getMore: 259896659504,
    collection: "searches",
    $db: "iodparts",
    lsid: {
        id: UUID("XXXXXXXXXX")
    }
  }
  originatingCommand: {
    find: "searches",
    filter: {
        mpn_alnum: {
            $gt: "8051"
        }
    },
    sort: {
        mpn_alnum: 1
    },
    $db: "iodparts",
    lsid: {
        id: UUID("XXXXXXX")
    }
  }
  planSummary: IXSCAN {
    mpn_alnum: 1
  }
  cursorid: XXXXXXXX keysExamined: 184421 docsExamined: 184421 numYields: 2694 nreturned: 184420 reslen: 16777182 locks: {
    Global: {
        acquireCount: {
            r: 5390
        }
    },
    Database: {
        acquireCount: {
            r: 2695
        }
    },
    Collection: {
        acquireCount: {
            r: 2695
        }
    }
  }
  protocol:op_msg 49796ms
  1. Наибольшее количество документов для то же mpn_alnum равно 5000. Обычно они меньше 1000.
  2. Количество документов в поисковой коллекции составляет 27 миллионов.

Вопрос Это каждый раз требуется 50-60 секунд для извлечения. Есть ли способ улучшить logi c или ускорить работу?

Обновление 1

Уточнения:

"запускать его несколько раз "означает оба: (а) получение результатов от курсора в течение нескольких минут. сохранил последнее значение возвращаемого поля. (b) В следующем запросе, взятом с того места, где слева, с помощью запроса $ gt. Кажется, это займет больше времени. Вывод журнала - это результат операции getMore для одного такого запроса.

Версия MongoDB: 3.6

WiredTiger - это движок.

Обновление 2

Я использовал три разные стратегии, которые помогли мне выбраться из этой проблемы.

A. Обновлен с MongoDB 3.6 до MongoDB 4.0

B. Удвоенный размер SDD и IOPS (операций ввода-вывода в секунду) - согласно стандартам AWS EC2 - с 200 ГБ до 400 ГБ. База данных приближалась к 190+ ГБ.

C. Переписан программный код с PHP 7 на NodeJS

Теперь все операции меньше 1сек. Это почти 50-кратное увеличение!

1 Ответ

1 голос
/ 18 мая 2020

keysExamined: 184421 docsExamined: 184421 numYields: 2694 nreturned: 184420

Эта строка предполагает, что размер пакета довольно большой. Размер пакета по умолчанию для курсора mon go составляет 100 документов, и если он установлен, журналы должны выглядеть примерно как keysExamined: 102 docsExamined: 101 numYields: 8 nreturned: 101. Таким образом, он не ждет, пока найдет 200 тыс. Документов, прежде чем сможет начать обработку.

Решение псевдокода на основе курсора, которое выполняет итерацию курсора и обрабатывает документы с тем же идентификатором группы, может выглядеть примерно так:

const cursor = collection.find({mpn_alnum: {$gte: x}, {batchSize: 100});
let docs = [];
for await (const doc of cursor) {
 if (docs.length && doc.mpn_alnum !== docs[0].mpn_alnum) {
   await processBatch(docs);
   docs = [];
 }
 docs.push(doc);
}

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

...