Před verzí 2.6 by interaktivní shell procházel smyčkou a pouze kontroloval úspěšnost (pomocí getLastError) poslední operace ve smyčce (konkrétněji se jmenovala getLastError po každém návratu vozíku, přičemž poslední operace je poslední vložení do smyčky). S verzí 2.6 bude nyní shell kontrolovat stav každé jednotlivé operace v rámci smyčky. V podstatě to znamená, že „pomalost“ u verze 2.6 lze připsat spíše potvrzenému a nepotvrzenému výkonu zápisu než skutečnému problému s výkonem jako takovým.
Potvrzené zápisy byly výchozí už nějakou dobu , a tak si myslím, že chování ve 2.6 je správnější, i když trochu nepohodlné pro ty z nás, kteří jsme zvyklí na původní chování.
Chcete-li se vrátit k předchozím úrovním výkonu, odpovědí je použití nového rozhraní API pro neuspořádané hromadné vkládání . Zde je časovaná verze:
> 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
To je nyní zpět k v podstatě stejnému výkonu za něco málo přes 2 sekundy. Jistě, je to trochu objemnější (promiňte, ale víte přesně, co dostáváte, což si myslím, že je obecně dobrá věc. Je zde také výhoda, když nehledáte informace o načasování. Pojďme se toho zbavit a spusťte vložku znovu:
> 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" : [ ]
})
Nyní dostáváme pěkný výsledný dokument, když provádíme hromadné vkládání, spíše než kontrolu pouze posledních operací (všechny ostatní ve verzi 2.4 byly v podstatě odeslány a zapomenout). Protože se jedná o neuspořádanou hromadnou operaci, bude pokračovat, pokud dojde k chybě, a bude o každé takové chybě hlásit v tomto dokumentu. Ve výše uvedeném příkladu nejsou žádné vidět, ale je snadné uměle vytvořit scénář selhání. Předem vložte hodnotu, o které víme, že se objeví, a proto způsobí chybu duplicitního klíče na (výchozím) jedinečném indexu _id:
> 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" : [ ]
})
Nyní můžeme vidět, kolik z nich bylo úspěšných, který z nich selhal (a proč). Nastavení může být trochu složitější, ale celkově si myslím, že jde o zlepšení.
Se vším, co bylo řečeno, a nastíněným novým preferovaným způsobem, existuje způsob, jak přinutit shell zpět do staršího režimu. To dává smysl, protože shell 2.6 se možná bude muset připojit ke starším serverům a pracovat s nimi. Pokud se připojíte k serveru 2.4, bude o to postaráno za vás, ale pro vynucení záležitosti pro konkrétní připojení můžete spustit:
db.getMongo().forceWriteMode("legacy");
Jakmile budete hotovi, můžete se vrátit zpět k verzi 2.6 pomocí:
db1.getMongo().forceWriteMode("commands");
Skutečné použití naleznete v mém úryvku crud.js . Toto zatím funguje, ale může být kdykoli v budoucnu bez upozornění odstraněno a opravdu není určeno pro rozsáhlé použití, takže jej používejte na vlastní riziko.