MongoDB - узкое место в производительности с простым запросом - PullRequest
1 голос
/ 26 сентября 2019

В настоящее время мы исследуем MongoDB как возможное решение для высокораспределенной базы данных научных данных.Учитывая наши требования к запросам, мы выбрали одну коллекцию, состоящую из документов, каждый документ представляет объект и его свойства, число которых ~ 450.Типичный документ должен быть структурирован следующим образом:

d = {'patch': '12345-1,1',
     'X': { (120 key-value pairs) },
     'A': { (64 key-value pairs) },
     ...
     (4 more such embedded documents)
    }

В X есть целочисленный флаг.Флаг представляет собой 32-битное целое число, каждый бит представляет логический флаг.Это распространенный метод хранения логических флагов, когда их число довольно велико.Существует таблица поиска, которая показывает, какая позиция соответствует какому логическому свойству.Существует 15-й бит, который имеет отношение к нашему конкретному набору запросов.Общее количество документов составляет 600 000, которые хранятся на 3 рабочих столах (8 ГБ ОЗУ и процессор i7, стандартные вращающиеся жесткие диски со скоростью 5400 об / мин).

Запрашиваемый запрос прост - нам нужно подсчет всех документов, для которых15-й бит определенного целого флага установлен в 1.

db.coll.find(
    {'X.flag1': {$bitsAllSet: [14]}}
).count()

Среднее время, затраченное на этот запрос, составляет 19 783 мс.Это не приемлемое время для нас.Мы попытались улучшить это с помощью агрегации вместо стандартного запроса find ().

db.coll.aggregate([
    '$match': {
        'X.flag1': {$bitsAllSet: [14]}
    },
    '$group': {
        _id: 0,
        count: {$sum: 1}
    }
])

Это занимает около 10000 мс.Хотя это улучшение (которое, я думаю, связано с высокоэффективной реализацией структуры агрегации на C ++), оно все еще выходит за рамки желаемой производительности.Следующим шагом было выделить флаг, скрытый в 15-м бите, и сделать его отдельным ключом в документе.Это приведет к тем же запросам, что и выше, но вместо использования $bitsAllSet: [14] мы будем использовать X.is_primary: 1.Для find () и aggregate () соответствующие времена составляли 19000 мс и 8500 мс соответственно.Улучшение очень незначительное.

Итак, два моих вопроса, с которыми, я надеюсь, люди могут помочь, это:

  • Является ли это последним результатом, который я могу ожидать от MongoDB Community Edition?Я знаю, что есть Enterprise Edition, который будет идти с In-Memory Engine.Но мой вопрос более специфичен для Community Edition.Есть ли какой-нибудь прием, который я мог бы использовать для ускорения запроса?
  • Я постепенно нахожу, что по крайней мере для сложной серверной аналитики и запросов, которые нам нужны, MongoDB оказывается трудным для использования обоих с точки зрениясложность запросов, которые мы пишем, а также узкие места производительности.Любые советы о том, какие другие базы данных я могу рассмотреть.

Редактировать: Как и предполагалось, я делюсь выводом .explain ().Вывод для коллекции, где is_primary не проиндексировано.Но, как обсуждалось в разделе комментариев, для логического значения наличие индекса не должно влиять на производительность запроса на основе логических флагов.

Pastebin Link (срок действия 2 недели)

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