Почему добавление индекса ухудшает производительность? - PullRequest
0 голосов
/ 09 сентября 2018

Я оцениваю производительность следующего запроса.

db.products_old.find({ regularPrice: { $lte: 200 } })

В собрании содержится чуть более миллиона документов, всего около 0,15 ГБ.


Нет индексов

Это ожидается. Полное сканирование столбца должно быть сделано

"executionTimeMillis" : 1019,

"winningPlan" : {
    "stage" : "COLLSCAN",
    "filter" : {
        "regularPrice" : {
            "$lte" : 200
        }
    },
    "direction" : "forward"
},

Индекс {регулярная цена: 1}

"executionTimeMillis" : 2842,

"winningPlan" : {
    "stage" : "FETCH",
    "inputStage" : {
        "stage" : "IXSCAN",
        "keyPattern" : {
            "regularPrice" : 1
        },
        "indexName" : "regularPrice_1",
        "isMultiKey" : false,
        "multiKeyPaths" : {
            "regularPrice" : [ ]
        },
        "isUnique" : false,
        "isSparse" : false,
        "isPartial" : false,
        "indexVersion" : 2,
        "direction" : "forward",
        "indexBounds" : {
            "regularPrice" : [
                "[-inf.0, 200.0]"
            ]
        }
    }
},

Теперь он использует индекс, но время выполнения заметно хуже. Почему?

Кроме того, если производительность хуже, почему Монго не использует COLLSCAN вместо индекса, который замедляет выполнение? rejectedPlans пусто, что говорит о том, что никакой другой план даже не рассматривался. Почему?


Вот полный allPlansExecution вывод.

1 Ответ

0 голосов
/ 09 сентября 2018

При выполнении COLLSCAN MongoDB считывает данные с накопителя и сохраняет соответствующие документы в оперативной памяти для последующего использования напрямую. С другой стороны, IXSCAN читает индекс, в котором хранятся индексированные данные и указатели на их расположение на диске. ( Вот хорошая визуализация от слайда 6 до слайда 20)

В вашей коллекции много документов, но в индексе также много подходящих документов. Данные, хранящиеся на накопителе, хранятся не лучшим образом, чтобы их можно было прочитать (например, в индексе), поэтому, когда IXSCAN возвращает указатели на 220k + документов, найденных для вашего запроса, FETCH необходимо читать 220k + раз с накопителя в режиме произвольного доступа. Который медленный. С другой стороны, я предполагаю, что COLLSCAN выполняет последовательное чтение, которое, вероятно, выполняется постранично и намного быстрее, чем FETCH читает.

Итак, подведем итог: не индекс замедляет вас, а стадия FETCH. Если вы все еще хотите использовать этот индекс и иметь более быстрое время выполнения запроса, используйте .select('-_id regularPrice'), который просто добавит быстрый этап PROJECTION и прочитает все необходимые поля из индекса. Или, если вам нужно _id, добавьте индекс {regularPrice: 1, _id: 1}.

А что касается части , почему использует Mongo для индексации, хотя он может знать, что сканирование коллекции происходит быстрее: я думаю, что если он увидит индекс, он будет его использовать. Но вы можете заставить его использовать сканирование коллекции с помощью метода hint с передачей {natural: 1}.

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