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

Warum sind Einfügungen in der MongoDB-Shell 2.6 im Vergleich zu früheren Versionen langsam?

Vor Version 2.6 durchlief die interaktive Shell die Schleife und überprüfte nur den Erfolg (unter Verwendung von getLastError) der letzten Operation in der Schleife (genauer gesagt, sie hieß getLastError nach jedem Wagenrücklauf, wobei die letzte Operation die letzte Einfügung in die Schleife ist). Mit 2.6 überprüft die Shell jetzt den Status jeder einzelnen Operation innerhalb der Schleife. Im Wesentlichen bedeutet dies, dass die "Langsamkeit" mit 2.6 eher auf bestätigte als nicht bestätigte Schreibleistung und nicht auf ein tatsächliches Leistungsproblem per se zurückgeführt werden kann.

Bestätigte Schreibvorgänge waren der Standard seit einiger Zeit , und daher denke ich, dass das Verhalten in 2.6 korrekter ist, obwohl es für diejenigen von uns, die an das ursprüngliche Verhalten gewöhnt sind, etwas unbequem ist.

Um zu Ihrem vorherigen Leistungsniveau zurückzukehren, ist die Antwort die Verwendung des neuen API für ungeordnete Masseneinfügung . Hier ist eine zeitgesteuerte Version:

> db.timecheck.drop();
true
> var bulk = db.timecheck.initializeUnorderedBulkOp(); start = new Date(); for(var i = 0; i < 100000; i++){bulk.insert({"_id" : i})}; bulk.execute({w:1}); end = new Date(); print(end - start);
2246

Das ist jetzt wieder im Wesentlichen die gleiche Leistung bei etwas mehr als 2 Sekunden. Sicher, es ist etwas voluminöser (verzeihen Sie das Wortspiel), aber Sie wissen genau, was Sie bekommen, was ich im Allgemeinen für eine gute Sache halte. Hier gibt es auch einen Vorteil, wenn Sie nicht nach Timing-Informationen suchen. Lassen Sie uns das loswerden und die Einfügung erneut ausführen:

> db.timecheck.drop();
true
> var bulk = db.timecheck.initializeUnorderedBulkOp(); for(var i = 0; i < 100000; i++){bulk.insert({"_id" : i})}; bulk.execute({w:1});
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 100000,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})

Jetzt erhalten wir ein schönes Ergebnisdokument, wenn wir die Masseneinfügung durchführen, anstatt nur die letzten Operationen zu überprüfen (der ganze Rest in der Version 2.4 war im Wesentlichen Senden und Vergessen). Da es sich um einen ungeordneten Massenvorgang handelt, wird er fortgesetzt, falls er auf einen Fehler stößt, und über jeden solchen Fehler in diesem Dokument berichten. Im obigen Beispiel sind keine zu sehen, aber es ist einfach, ein Ausfallszenario künstlich zu erstellen. Lassen Sie uns einfach einen Wert vorab einfügen, von dem wir wissen, dass er auftaucht und daher einen doppelten Schlüsselfehler im (standardmäßigen) eindeutigen _id-Index verursacht:

> db.timecheck.drop();
true
> db.timecheck.insert({_id : 500})
WriteResult({ "nInserted" : 1 })
> var bulk = db.timecheck.initializeUnorderedBulkOp(); for(var i = 0; i < 100000; i++){bulk.insert({"_id" : i})}; bulk.execute({w:1});
2014-03-28T16:19:40.923+0000 BulkWriteError({
"writeErrors" : [
{
"index" : 500,
"code" : 11000,
"errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.timecheck.$_id_ dup key: { : 500.0 }",
"op" : {
"_id" : 500
}
}
],
"writeConcernErrors" : [ ],
"nInserted" : 99999,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})

Jetzt können wir sehen, wie viele erfolgreich waren, welche gescheitert sind (und warum). Die Einrichtung ist vielleicht etwas komplizierter, aber insgesamt denke ich, dass es eine Verbesserung ist.

Nachdem all dies gesagt und der neue bevorzugte Weg skizziert wurde, gibt es eine Möglichkeit, die Shell zurück in den Legacy-Modus zu zwingen. Dies ist sinnvoll, da eine 2.6-Shell möglicherweise eine Verbindung zu älteren Servern herstellen und mit diesen arbeiten muss. Wenn Sie sich mit einem 2.4-Server verbinden, wird dies für Sie erledigt, aber um die Angelegenheit für eine bestimmte Verbindung zu erzwingen, können Sie Folgendes ausführen:

db.getMongo().forceWriteMode("legacy");

Sobald Sie fertig sind, können Sie mit:

zur Version 2.6 zurückkehren
db1.getMongo().forceWriteMode("commands");

Informationen zur tatsächlichen Verwendung finden Sie in meinem crud.js-Snippet . Dies funktioniert vorerst, kann aber zu einem späteren Zeitpunkt ohne Vorankündigung entfernt werden und ist wirklich nicht für eine umfassende Nutzung gedacht, also auf eigene Gefahr.