Index

Index em mongoDB assim como outros bancos de dados são extremamente importante para auxiliar nas buscas por determinado valor. Durante a busca de uma coleção os indexes ajudam na performance das buscas. Mas cuidado sempre é mais eficiente realizar testes de perfomance e estudos para o banco ser mais performático.

Vamos criar um Index no MongoDB

> db.restaurantes.createIndex({name:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}

Detalhe importante, esse valor usado no “name” é para identifica a ordem do index:

1: Para Ordem Crescente (A-Z)

ou

-1: Para Ordem Descrecente (Z-A)

Quando você cria uma coleção, automaticamente o mongoDB já cria o index dos _id’s. Para vermos todos os indexes podemos utilizar o comando getIndexes().

> db.restaurantes.getIndexes()
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "be-mean.restaurantes"
        },
        {
                "v" : 1,
                "key" : {
                        "name" : 1
                },
                "name" : "name_1",
                "ns" : "be-mean.restaurantes"
        }
]

Então agora para nossa coleção temos dois indexes, um de “_id” e o outro de “name”. Hmmm, é dai? E dai que agora as buscas por nome serão muito mais performáticas pois elas utilizaram esse index criado, vamos fazer então um comparativo, primeiro vamos buscar os dados sem utilizar os index e no segundo momento busquemos os dados após a criação do Index.

Buscando por “name” sem index
> query
{ "name" : "Dunkin' Donuts, Baskin Robbins" }
> db.restaurantes.find(query).explain('executionStats').executionStats.executionTimeMillis
15
Após a criação do index “name”
> query
{ "name" : "Dunkin' Donuts, Baskin Robbins" }
> db.restaurantes.find(query).explain('executionStats').executionStats.executionTimeMillis
0

Vejamos todos os dados retornados usando explain com ‘executionStats’

> db.restaurantes.find(query).explain('executionStats').executionStats
{
        "executionSuccess" : true,
        "nReturned" : 55,
        "executionTimeMillis" : 0,
        "totalKeysExamined" : 55,
        "totalDocsExamined" : 55,
        "executionStages" : {
                "stage" : "FETCH",
                "nReturned" : 55,
                "executionTimeMillisEstimate" : 0,
                "works" : 56,
                "advanced" : 55,
                "needTime" : 0,
                "needFetch" : 0,
                "saveState" : 0,
                "restoreState" : 0,
                "isEOF" : 1,
                "invalidates" : 0,
                "docsExamined" : 55,
                "alreadyHasObj" : 0,
                "inputStage" : {
                        "stage" : "IXSCAN",
                        "nReturned" : 55,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 56,
                        "advanced" : 55,
                        "needTime" : 0,
                        "needFetch" : 0,
                        "saveState" : 0,
                        "restoreState" : 0,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "keyPattern" : {
                                "name" : 1
                        },
                        "indexName" : "name_1",
                        "isMultiKey" : false,
                        "direction" : "forward",
                        "indexBounds" : {
                                "name" : [
                                        "[\"Dunkin' Donuts, Baskin Robbins\", \"Dunkin' Donuts, Baskin Robbins\"]"
                                ]
                        },
                        "keysExamined" : 55,
                        "dupsTested" : 0,
                        "dupsDropped" : 0,
                        "seenInvalidated" : 0,
                        "matchTested" : 0
                }
        }
}

Para excluir o index criado usamos a função dropIndex

> db.restaurantes.dropIndex({ name : 1})
{ "nIndexesWas" : 2, "ok" : 1 }

Após a exclusão do index

> db.restaurantes.find(query).explain('executionStats').executionStats
{
        "executionSuccess" : true,
        "nReturned" : 55,
        "executionTimeMillis" : 15,
        "totalKeysExamined" : 0,
        "totalDocsExamined" : 25359,
        "executionStages" : {
                "stage" : "COLLSCAN",
                "filter" : {
                        "name" : {
                                "$eq" : "Dunkin' Donuts, Baskin Robbins"
                        }
                },
                "nReturned" : 55,
                "executionTimeMillisEstimate" : 10,
                "works" : 25361,
                "advanced" : 55,
                "needTime" : 25305,
                "needFetch" : 0,
                "saveState" : 198,
                "restoreState" : 198,
                "isEOF" : 1,
                "invalidates" : 0,
                "direction" : "forward",
                "docsExamined" : 25359
        }
}

A criação de index aceita multiplos valores, mas lembre-se ele somente utilizará esse index caso a busca siga com os valores criado, por exemplo:

> db.restaurantes.createIndex({ name : 1 , borough : 1 })
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
}

Utilizando “name” e “borough” (nome e bairro) vamos agora fazer um busca com esses dois valores na query.

> var query = {"name" : "Dunkin' Donuts, Baskin Robbins", "borough" : "Manhattan"}
> db.restaurantes.find(query).explain('executionStats').executionStats
{
        "executionSuccess" : true,
        "nReturned" : 20,
        "executionTimeMillis" : 36,
        "totalKeysExamined" : 20,
        "totalDocsExamined" : 20,
        "executionStages" : {
                "stage" : "FETCH",
                "nReturned" : 20,
                "executionTimeMillisEstimate" : 0,
                "works" : 22,
                "advanced" : 20,
                "needTime" : 0,
                "needFetch" : 0,
                "saveState" : 1,
                "restoreState" : 1,
                "isEOF" : 1,
                "invalidates" : 0,
                "docsExamined" : 20,
                "alreadyHasObj" : 0,
                "inputStage" : {
                        "stage" : "IXSCAN",
                        "nReturned" : 20,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 21,
                        "advanced" : 20,
                        "needTime" : 0,
                        "needFetch" : 0,
                        "saveState" : 1,
                        "restoreState" : 1,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "keyPattern" : {
                                "name" : 1,
                                "borough" : 1
                        },
                        "indexName" : "name_1_borough_1",
                        "isMultiKey" : false,
                        "direction" : "forward",
                        "indexBounds" : {
                                "name" : [
                                        "[\"Dunkin' Donuts, Baskin Robbins\", \"Dunkin' Donuts, Baskin Robbins\"]"
                                ],
                                "borough" : [
                                        "[\"Manhattan\", \"Manhattan\"]"
                                ]
                        },
                        "keysExamined" : 20,
                        "dupsTested" : 0,
                        "dupsDropped" : 0,
                        "seenInvalidated" : 0,
                        "matchTested" : 0
                }
        }
}

Podemos destacar a utilização do index criado anteriormente

"indexBounds" : {
        "name" : [
                "[\"Dunkin' Donuts, Baskin Robbins\", \"Dunkin' Donuts, Baskin Robbins\"]"
        ],
        "borough" : [
                "[\"Manhattan\", \"Manhattan\"]"
        ]
}

Tempo de busca:

"executionTimeMillis" : 36,

Documentos analisados:

"docsExamined" : 20,

Compartilhe

Back