MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mongo-Abfrage dauert lange. Wie schneller machen?

Der Index müsste den gesamten Teil der Abfrage abdecken (Gleichheitsteil, Sortierteil und Bereichsteil). Dies liegt daran, dass in einem typischen find() Abfrage verwendet MongoDB nur einen Index. Beispielsweise verwendet es im Allgemeinen nicht einen Index für den Gleichheitsteil und einen anderen Index für den Sortierungsteil.

Im Allgemeinen muss die Reihenfolge der Felder im Index dem Muster Gleichheit -> Sortierung -> Bereich folgen .

Dies wird ausführlich in Optimierung zusammengesetzter MongoDB-Indizes beschrieben .

Für Ihre Abfrage ist der Gleichheitsteil tag:..., letterId:... und der Sortierteil ist emailId:-1 . Ihre Abfrage enthält keinen Bereichsteil.

Unter Verwendung dieses Musters ist der zusammengesetzte Index, den Sie benötigen:

db.test.createIndex({tag:1, letterId:1, emailId:-1})

Lassen Sie uns versuchen zu bestätigen, wie viel Leistungsverbesserung wir mit diesem Index erzielen können.

Testdaten

Um die Eignung des Index zu bestätigen, habe ich 1 Million Datensätze mit mgeneratejs in eine Testdatenbank eingefügt , ein Tool zum Erstellen eines zufälligen Dokuments mithilfe einer Vorlage.

Basierend auf Ihrem Beispiel, den mgeneratejs Vorlage, die ich verwende, ist:

$ 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}}}}
}

und importierte 1 Million zufällige Dokumente in MongoDB:

$ mgeneratejs template.json -n 1000000 | mongoimport -d test -c test

Test 1:nicht optimaler Index

Dann erstelle ich den Index, den Sie haben, und habe versucht, ein nicht vorhandenes Dokument zu finden, und 10 Durchläufe der Abfrage mit der Sammlung gesammelt, die nur diesen Index enthält:

> 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

Wenn Sie also diesen Index verwenden, sind die Antwortzeiten der Abfrage nicht besonders gut, da die meisten Ausführungen in der Nähe von 3 Sekunden liegen.

Test 2:Gleichheit -> Sortierung -> Bereichsindex

Durch Hinzufügen der optimalen Gleichheit -> Sortierung -> Bereich 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

Im Gegensatz dazu wurde die Leistung unter Verwendung des optimalen Index deutlich verbessert. Keine Abfrage wurde in mehr als 3 ms zurückgegeben, wobei die überwiegende Zeit in 1 ms zurückgegeben wird.