Um índice composto faz referência a vários campos e pode melhorar drasticamente os tempos de resposta da query.
Na maioria dos casos, a aplicação da diretriz ESR (Equality, Sort, Range) para organizar as chaves do índice cria um índice compostomais eficiente.
Garanta que os campos de igualdade sempre estejam em primeiro lugar. A colocação dos campos de igualdade primeiro mantém os campos de índice restantes em uma ordem definida. Escolha se deseja usar um campo de classificação ou faixa em seguida com base nas necessidades específicas do seu índice:
Se evitar classificações na memória for fundamental, coloque os campos de classificação antes dos campos de intervalo (ESR)
Se o seu predicado de intervalo na query for muito seletivo, coloque-o antes dos campos de classificação (ERS)
Para saber mais sobre como otimizar queries, consulte explain e Planos de queries.
Dica
Para forçar o MongoDB a usar um índice específico, use cursor.hint() (método mongosh) ao testar índices.
Igualdade
Os exemplos nesta página utilizam dados do sample_mflix sample dataset. Para obter detalhes sobre como carregar esse conjunto de dados em sua implantação autogerenciada do MongoDB , consulte Carregar o conjunto de dados de amostra. Se você fez modificações nos bancos de dados de amostra, talvez seja necessário descartar e recriar os bancos de dados para executar os exemplos nesta página.
"Igualdade" refere-se a uma correspondência exata em um único valor. As seguintes consultas de correspondência exata verificam a coleção movies em busca de documentos cujo campo title corresponda exatamente a Equilibrium.
db.movies.find( { title: "Equilibrium" }, { title: 1, year: 1, cast: 1 } )
[ { _id: ObjectId('573a13a3f29313caabd0c8d2'), year: 2002, title: 'Equilibrium', cast: [ 'Christian Bale', 'Dominic Purcell', 'Sean Bean', 'Christian Kahrmann' ] } ]
db.movies.find( { title: { $eq: "Equilibrium" } }, { title: 1, year: 1, cast: 1 } )
[ { _id: ObjectId('573a13a3f29313caabd0c8d2'), year: 2002, title: 'Equilibrium', cast: [ 'Christian Bale', 'Dominic Purcell', 'Sean Bean', 'Christian Kahrmann' ] } ]
As pesquisas de índice fazem uso eficiente de correspondências exatas para reduzir o número de chaves de índice examinadas. Os campos de igualdade devem vir em primeiro lugar.
Um índice pode ter múltiplas chaves de igualdade. Elas podem aparecer em qualquer ordem relativa uma à outra, mas todas as chaves de igualdade devem preceder quaisquer campos de classificação ou faixa.
Quanto mais seletivas as correspondências de igualdade, mais eficiente é a query indexada.
Sort
"Classificar" determina a ordem dos resultados. Para evitar classificações na memória, coloque campos de classificação antes de faixas no índice.
Um índice suporta operações de classificação em um subconjunto de suas chaves somente quando a consulta inclui condições de igualdade em todas as chaves de prefixo que precedem as chaves de classificação. Para obter mais informações, consulte Classificação e Subconjunto sem Prefixo de um Índice.
O exemplo a seguir consulta a collection movies para filmes em que o campo directors contém "David Lynch". A saída é classificada por year:
db.movies.find( { directors: "David Lynch" }, { title: 1, year: 1 } ).sort( { year: 1 } )
[ { _id: ObjectId('573a1397f29313caabce77d4'), title: 'The Elephant Man', year: 1980 }, { _id: ObjectId('573a1398f29313caabce9091'), title: 'Dune', year: 1984 }, { _id: ObjectId('573a1398f29313caabce9e12'), title: 'Blue Velvet', year: 1986 }, { _id: ObjectId('573a1399f29313caabced630'), year: 1992, title: 'Twin Peaks: Fire Walk with Me' }, { _id: ObjectId('573a139af29313caabcf00f0'), year: 1997, title: 'Lost Highway' }, { _id: ObjectId('573a139ef29313caabcfbc0e'), year: 1999, title: 'The Straight Story' }, { _id: ObjectId('573a139ef29313caabcfbc36'), title: 'Mulholland Drive', year: 2001 }, { _id: ObjectId('573a13b4f29313caabd40a54'), title: 'Inland Empire', year: 2006 } ]
Para melhorar o desempenho da consulta, crie um índice nos campos directors e year:
db.movies.createIndex( { directors: 1, year: 1 } )
directorsé a primeira chave porque é uma correspondência de igualdade.yearé indexado na mesma ordem (1) que a consulta.
faixa
Filtros de "faixa" verificam campos. A verificação não requer uma correspondência exata, o que significa que os filtros de faixa estão vagamente vinculados às chaves de índice. Para aumentar a eficiência da query, limite as faixas e use correspondências de igualdade para reduzir o número de documentos a serem verificados.
Filtros de faixa se assemelham ao seguinte:
db.movies.find( { runtime: { $gte: 1000 } }, { title: 1, runtime: 1, year: 1, plot: 1 } )
[ { _id: ObjectId('573a1397f29313caabce69db'), plot: 'The economic and cultural growth of Colorado spanning two centuries from the mid-1700s to the late-1970s.', runtime: 1256, title: 'Centennial', year: 1978 }, { _id: ObjectId('573a1399f29313caabcee1aa'), plot: 'A documentary on the history of the sport with major topics including Afro-American players, player/team owner relations and the resilience of the game.', runtime: 1140, title: 'Baseball', year: 1994 } ]
db.movies.find( { year: { $lt: 1900 } }, { title: 1, year: 1, plot: 1 } )
[ { _id: ObjectId('573a139cf29313caabcf560f'), plot: 'Two people kiss.', title: 'The Kiss', year: 1896 }, { _id: ObjectId('573a13a0f29313caabd041db'), plot: 'Two people kiss.', title: 'The Kiss', year: 1896 } ]
db.movies.find( { type: { $ne: "movie" } }, { title: 1, year: 1, type: 1 } )
[ { _id: ObjectId('573a1395f29313caabce2f03'), title: 'The Forsyte Saga', year: 1967, type: 'series' }, { _id: ObjectId('573a1396f29313caabce520d'), title: 'Scenes from a Marriage', year: 1973, type: 'series' }, { _id: ObjectId('573a1396f29313caabce5b86'), title: 'Ironiya sudby, ili S legkim parom!', year: 1975, type: 'series' }, { _id: ObjectId('573a1397f29313caabce6378'), title: 'Sybil', year: 1976, type: 'series' }, { _id: ObjectId('573a1397f29313caabce6443'), title: 'Jesus of Nazareth', year: 1977, type: 'series' } ]
Se o predicado de intervalo em sua query for muito seletivo, coloque-o antes dos campos de classificação para reduzir o número de documentos classificados e permitir uma classificação na memória.
Para evitar uma classificação in-memory, coloque o filtro de faixa após o predicado de classificação. Para obter mais informações sobre classificações in-memory, consulte cursor.allowDiskUse().
Considerações adicionais
Operadores de desigualdade, como
$neou$ninsão operadores de alcance, não operadores de igualdade.$regexé um operador de alcance.Quando
$iné utilizado sozinho, é um operador de igualdade que executa uma série de correspondências de igualdade.Quando
$iné usado com.sort():Se
$intiver menos de 201 elementos de array, os elementos serão expandidos e, em seguida, mesclados na ordem de classificação especificada para o índice usando um estágioSORT_MERGE. Isso melhora o desempenho de arrays pequenas. Neste caso,$iné semelhante a um predicado de igualdade com ESR.Se
$intiver 201 elementos ou mais, os elementos serão ordenados como um operador de faixa. Nesse caso, a melhoria de desempenho para arrays pequenas não é realizada. Não é possível que os campos subsequentes no índice sejam usados para classificação, e$iné semelhante a um predicado de faixa com ESR.Se você normalmente usa operadores
$incom arrays pequenas, inclua-os anteriormente na especificação do índice. Se você normalmente usa arrays grandes, inclua operadores$inonde incluiria um predicado de faixa.
Observação
Não é garantido que a mudança de comportamento $in em 201 elementos de array permaneça a mesma em todas as versões do MongoDB .
Exemplo
A seguinte query pesquisa a coleção movies para filmes onde o campo directors é "David Lynch" e o campo runtime é menor que 130 minutos. Os resultados são classificados por year:
db.movies.find( { directors: "David Lynch", runtime: { $lt: 130 } }, { title: 1, year: 1, runtime: 1 } ).sort( { year: 1 } )
[ { _id: ObjectId('573a1397f29313caabce77d4'), runtime: 124, title: 'The Elephant Man', year: 1980 }, { _id: ObjectId('573a1398f29313caabce9e12'), runtime: 120, title: 'Blue Velvet', year: 1986 }, { _id: ObjectId('573a139ef29313caabcfbc0e'), year: 1999, title: 'The Straight Story', runtime: 112 } ]
A query contém todos os elementos da Diretriz ESR:
directors: "David Lynch"é uma correspondência baseada em igualdaderuntime: { $lt: 130 }é uma correspondência baseada em faixayearé usado para classificar
Seguindo a diretriz ESR, o índice ideal para a query de exemplo é:
{ directors: 1, year: 1, runtime: 1 }