MongoDB: снижение производительности запросов

У меня есть коллекция пользователей в MongoDB с более чем 2,5 миллионами записей, которые составляют 30 ГБ. У меня около 4-6 ГБ индексов. Он находится в окружении с двумя осколками, каждый из которых состоит из набора реплик. Серверы предназначены специально для Mongo без накладных расходов. Общий объем ОЗУ превышает 10 ГБ, что более чем достаточно для запросов, которые я выполняю (показано ниже).

Меня беспокоит то, что, несмотря на наличие индексов для соответствующих полей, время получения результата огромно (от 2 минут до колоссальных 30 минут), что недопустимо. Я новичок в MongoDB и действительно в замешательстве, почему это происходит.

Пример схемы:

user:
{
_id: UUID (indexed by default),
name: string,
dob: ISODate,
addr: string,
createdAt: ISODate (indexed),
.
.
.,
transaction:[
{
firstTransaction: ISODate(indexed),
lastTransaction: ISODate(indexed),
amount: float,
product: string (indexed),
.
.
.
},...
],
other sub documents...
}

Длина дополнительного документа варьируется от 0 до 50 или около того.

Запросы, которые я выполнил:

1) db.user.find().min({createdAt:ISODate("2014-12-01")}).max({createdAt:ISODate("2014-12-31")}).explain()

Сначала этот запрос работал медленно, но потом был молниеносно (наверное, из-за прогрева).

2) db.user.find({transaction:{$elemMatch:{product:'mobile'}}}).explain()

Этот запрос занял более 30 минут, и разогрев не помог, так как каждый раз производительность была одинаковой. Вернулось более половины коллекции.

3) db.user.find({transaction:{$elemMatch:{product:'mobile'}}, firstTransaction:{$in:[ISODate("2015-01-01"),ISODate("2015-01-02")]}}}}).explain()

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

db.user.find({transaction:{$elemMatch:{product:'mobile'}}}).min({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-01")}}}).max({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-02")}}}).explain()

Этот запрос дал мне ошибку:

планировщик вернул ошибку: не удалось найти соответствующий индекс для запроса max/min и с подсказкой ():

planner returned error: hint provided does not work with min query

Я использовал функцию min max из-за неопределенности запросов диапазона в MongoDB с операторами $lt, $gt, которые иногда игнорируют любой из связанных и заканчивают сканирование большего количества документов, чем необходимо.

Я использовал такие индексы как:

db.user.ensureIndex({createdAt: 1})

db.user.ensureIndex({"transaction.firstTransaction":1})

db.user.ensureIndex({"transaction.lastTransaction":1})

db.user.ensureIndex({"transaction.product":1})

Я попытался использовать составную индексацию для запроса 3, который:

db.user.ensureIndex({"transaction.firstTransaction":1, "transaction.product":1})

Но это, кажется, не дает мне результата. Запрос застревает и никогда не возвращает результат. Я серьезно. НИКОГДА. Как в тупике. Я не знаю почему. Таким образом, я опустил этот индекс и получил результат после ожидания более получаса (очень расстраивает).

Пожалуйста, помогите мне, потому что я действительно отчаянно нуждаюсь в поиске решения и идей.

Этот вывод может помочь:

Following is the output for:

запрос:

db.user.find({transaction:{$elemMatch:{product:"mobile", firstTransaction:{$gte:ISODate("2015-01-01"), $lt:ISODate("2015-01-02")}}}}).hint("transaction.firstTransaction_1_transaction.product_1").explain()

выход:

{
        "clusteredType" : "ParallelSort",
        "shards" : {
                "test0/mrs00.test.com:27017,mrs01.test.com:27017" : [
                        {
                                "cursor" : "BtreeCursor transaction.product_1_transaction.firstTransaction_1",
                                "isMultiKey" : true,
                                "n" : 622,
                                "nscannedObjects" : 350931,
                                "nscanned" : 352000,
                                "nscannedObjectsAllPlans" : 350931,
                                "nscannedAllPlans" : 352000,
                                "scanAndOrder" : false,
                                "indexOnly" : false,
                                "nYields" : 119503,
                                "nChunkSkips" : 0,
                                "millis" : 375693,
                                "indexBounds" : {
                                        "transaction.product" : [
                                                [
                                                        "mobile",
                                                        "mobile"
                                                ]
                                        ],
                                        "transaction.firstTransaction" : [
                                                [
                                                        true,
                                                        ISODate("2015-01-02T00:00:00Z")
                                                ]
                                        ]
                                },
                                "server" : "ip-12-0-0-31:27017",
                                "filterSet" : false
                        }
                ],
                "test1/mrs10.test.com:27017,mrs11.test.com:27017" : [
                        {
                                "cursor" : "BtreeCursor transaction.product_1_transaction.firstTransaction_1",
                                "isMultiKey" : true,
                                "n" : 547,
                                "nscannedObjects" : 350984,
                                "nscanned" : 352028,
                                "nscannedObjectsAllPlans" : 350984,
                                "nscannedAllPlans" : 352028,
                                "scanAndOrder" : false,
                                "indexOnly" : false,
                                "nYields" : 132669,
                                "nChunkSkips" : 0,
                                "millis" : 891898,
                                "indexBounds" : {
                                        "transaction.product" : [
                                                [
                                                        "mobile",
                                                        "mobile"
                                                ]
                                        ],
                                        "transaction.firstTransaction" : [
                                                [
                                                        true,
                                                        ISODate("2015-01-02T00:00:00Z")
                                                ]
                                        ]
                                },
                                "server" : "ip-12-0-0-34:27017",
                                "filterSet" : false
                        }
                ]
        },
        "cursor" : "BtreeCursor transaction.product_1_transaction.firstTransaction_1",
        "n" : 1169,
        "nChunkSkips" : 0,
        "nYields" : 252172,
        "nscanned" : 704028,
        "nscannedAllPlans" : 704028,
        "nscannedObjects" : 701915,
        "nscannedObjectsAllPlans" : 701915,
        "millisShardTotal" : 1267591,
        "millisShardAvg" : 633795,
        "numQueries" : 2,
        "numShards" : 2,
        "millis" : 891910
}

Запрос:

db.user.find({transaction:{$elemMatch:{product:'mobile'}}}).explain()

Выход:

{
        "clusteredType" : "ParallelSort",
        "shards" : {
                "test0/mrs00.test.com:27017,mrs01.test.com:27017" : [
                        {
                                "cursor" : "BtreeCursor transaction.product_1",
                                "isMultiKey" : true,
                                "n" : 553072,
                                "nscannedObjects" : 553072,
                                "nscanned" : 553072,
                                "nscannedObjectsAllPlans" : 553072,
                                "nscannedAllPlans" : 553072,
                                "scanAndOrder" : false,
                                "indexOnly" : false,
                                "nYields" : 164888,
                                "nChunkSkips" : 0,
                                "millis" : 337909,
                                "indexBounds" : {
                                        "transaction.product" : [
                                                [
                                                        "mobile",
                                                        "mobile"
                                                ]
                                        ]
                                },
                                "server" : "ip-12-0-0-31:27017",
                                "filterSet" : false
                        }
                ],
                "test1/mrs10.test.com:27017,mrs11.test.com:27017" : [
                        {
                                "cursor" : "BtreeCursor transaction.product_1",
                                "isMultiKey" : true,
                                "n" : 554176,
                                "nscannedObjects" : 554176,
                                "nscanned" : 554176,
                                "nscannedObjectsAllPlans" : 554176,
                                "nscannedAllPlans" : 554176,
                                "scanAndOrder" : false,
                                "indexOnly" : false,
                                "nYields" : 107496,
                                "nChunkSkips" : 0,
                                "millis" : 327928,
                                "indexBounds" : {
                                        "transaction.product" : [
                                                [
                                                        "mobile",
                                                        "mobile"
                                                ]
                                        ]
                                },
                                "server" : "ip-12-0-0-34:27017",
                                "filterSet" : false
                        }
                ]
        },
        "cursor" : "BtreeCursor transaction.product_1",
        "n" : 1107248,
        "nChunkSkips" : 0,
        "nYields" : 272384,
        "nscanned" : 1107248,
        "nscannedAllPlans" : 1107248,
        "nscannedObjects" : 1107248,
        "nscannedObjectsAllPlans" : 1107248,
        "millisShardTotal" : 665837,
        "millisShardAvg" : 332918,
        "numQueries" : 2,
        "numShards" : 2,
        "millis" : 337952
}

Пожалуйста, дайте мне знать, если я пропустил какие-либо детали.

Благодарю.

2 ответа

Решение

Причиной снижения производительности стал большой рабочий набор. Для некоторых запросов (главным образом, запросов диапазона) набор превысил физический лимит и произошли сбои страниц. Из-за этого производительность стала ухудшаться. Одним из решений, которое я сделал, было применение нескольких фильтров для запроса, которые будут ограничивать набор результатов и пытаться выполнить проверку на равенство вместо диапазона (итерации по диапазону). Эти настройки работали на меня. Надеюсь, что это помогает другим.

1-й: Ваши запросы слишком сложны. Использование $elemMatch слишком часто. 2-й: если вы можете включить свой ключ в запросе, это значительно улучшит скорость.

Я собираюсь оптимизировать ваши запросы для вас:

db.user.find({
     createdAt: {
          $gte: ISODate("2014-12-01"), 
          $lte: ISODate("2014-12-31")
     }
}).explain()

db.user.find({
    'transaction.product':'mobile'
}).explain()

db.user.find({
    'transaction.product':'mobile', 
    firstTransaction:{
       $in:[
           ISODate("2015-01-01"),
           ISODate("2015-01-02")
       ]
    }
}).explain()

Суть в следующем: включайте ваш ключ осколка каждый раз, когда вы экономите время.

Это может даже сэкономить время на обход ваших ключей шарда и выполнение одного и того же запроса несколько раз.

Другие вопросы по тегам