Index by musel pokrýt celou část dotazu (část rovnosti, část řazení a část rozsahu). Je to proto, že v typickém find()
dotaz, MongoDB používá pouze jeden index. Například obecně nepoužívá jeden index pro část rovnosti a další index pro část řazení.
Obecně platí, že sekvence polí v indexu musí odpovídat vzoru rovnost -> řazení -> rozsah .
To je podrobně popsáno v Optimalizace složených indexů MongoDB .
Pro váš dotaz je část rovnosti tag:..., letterId:...
a část řazení je emailId:-1
. Ve vašem dotazu není žádná část rozsahu.
Pomocí tohoto vzoru potřebujete složený index:
db.test.createIndex({tag:1, letterId:1, emailId:-1})
Pokusme se potvrdit, jak velké zlepšení výkonu můžeme dosáhnout pomocí tohoto indexu.
Testovací údaje
Abych potvrdil vhodnost indexu, vložil jsem 1 milion záznamů do testovací databáze pomocí mgeneratejs , což je nástroj pro vytvoření náhodného dokumentu pomocí šablony.
Na základě vašeho příkladu mgeneratejs
šablona, kterou používám, je:
$ 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}}}}
}
a importoval 1 milion náhodných dokumentů do MongoDB:
$ mgeneratejs template.json -n 1000000 | mongoimport -d test -c test
Test 1:Neoptimální index
Poté vytvořím index, který máte, a pokusil jsem se najít neexistující dokument a shromáždil 10 spuštění dotazu s kolekcí obsahující pouze tento index:
> 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
takže při použití tohoto indexu nejsou doby odezvy dotazu skvělé, většina provedení se blíží 3 sekundám.
Test 2:rovnost -> řazení -> index rozsahu
Přidáním optimální rovnost -> řazení -> rozsah index:
> 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
Naproti tomu při použití optimálního indexu se výkon výrazně zlepšil. Žádný dotaz se nevrátí za více než 3 ms, přičemž ve velké většině případů se vrátí za 1 ms.