MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

A consulta do Mongo leva muito tempo. Como torná-lo mais rápido?


O índice precisaria cobrir toda a parte da consulta (parte de igualdade, parte de classificação e parte de intervalo). Isso ocorre porque em um típico find() consulta, o MongoDB usa apenas um índice. Por exemplo, geralmente não usa um índice para a parte de igualdade e outro índice para a parte de classificação.

Em geral, a sequência de campos no índice precisa seguir o padrão de igualdade -> classificação -> intervalo .

Isso é descrito em detalhes em Otimizando índices compostos do MongoDB .

Para sua consulta, a parte de igualdade é tag:..., letterId:... e a parte de classificação é emailId:-1 . Não há parte de intervalo em sua consulta.

Usando este padrão, o índice composto que você precisa é:
db.test.createIndex({tag:1, letterId:1, emailId:-1})

Vamos tentar confirmar quanta melhoria de desempenho podemos obter usando esse índice.

Dados de teste


Para confirmar a adequação do índice, inseri 1 milhão de registros em um banco de dados de teste usando mgeneratejs , que é uma ferramenta para criar um documento aleatório usando um modelo.

Com base no seu exemplo, o mgeneratejs template que estou usando é:
$ cat template.json
{
  "emailId": "$hash",
  "email": "$email",
  "letterId": "$hash",
  "sendedFrom": "$email",
  "resultMsg": "$word",
  "owner": "$name",
  "created": "$date",
  "result": "$bool",
  "tag": "$word",
  "tryNum": {"$integer": {"min": 0, "max": 1e3}},
  "clickHash": "$word",
  "links": {"$array": {"of": "$url", "number": {"$integer": {"min": 1, "max": 5}}}}
}

e importou 1 milhão de documentos aleatórios para o MongoDB:
$ mgeneratejs template.json -n 1000000 | mongoimport -d test -c test

Teste 1:índice não ideal


Então eu crio o índice que você tem, e tentei encontrar um documento inexistente e reuni 10 execuções da consulta com a coleção contendo apenas este índice:
> db.test.createIndex({emailId: 1, letterId: 1, result: 1, owner: 1, tag: 1, clickHash: 1})

> db.test.find({"tag" : "xyz", "letterId" : "abc"}).sort({emailId: -1}).limit(1)
Fetched 0 record(s) in 3069ms
Fetched 0 record(s) in 2924ms
Fetched 0 record(s) in 2923ms
Fetched 0 record(s) in 3013ms
Fetched 0 record(s) in 2917ms
Fetched 0 record(s) in 2961ms
Fetched 0 record(s) in 2882ms
Fetched 0 record(s) in 2870ms
Fetched 0 record(s) in 2969ms
Fetched 0 record(s) in 2863ms

então, usando esse índice, os tempos de resposta da consulta não são grandes, com a maioria das execuções próximas a 3 segundos.

Teste 2:igualdade -> classificação -> índice de intervalo


Ao adicionar a igualdade -> classificação -> intervalo ideal índice:
> db.test.createIndex({tag:1, letterId:1, emailId:-1})

> db.test.find({"tag" : "xyz", "letterId" : "abc"}).sort({emailId: -1}).limit(1)
Fetched 0 record(s) in 2ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 1ms
Fetched 0 record(s) in 3ms

Em contraste, usando o índice ótimo, o desempenho foi significativamente melhorado. Nenhuma consulta retornou em mais de 3ms, com a grande maioria das vezes retornando em 1ms.