Преди 2.6 интерактивната обвивка преминаваше през цикъла и проверяваше само успеха (използвайки getLastError) на последната операция в цикъла (по-конкретно, наричаше getLastError след всяко връщане на каретка, като последната операция е последното вмъкване в цикъла). С 2.6 обвивката вече ще проверява състоянието на всяка отделна операция в рамките на цикъла. По същество това означава, че „бавността“ с 2.6 може да се отдаде на производителността на потвърдено срещу непотвърдено записване, а не на действителен проблем с производителността сам по себе си.
Потвърдените записвания са били по подразбиране от известно време и затова мисля, че поведението в 2.6 е по-правилно, макар и малко неудобно за онези от нас, които са свикнали с оригиналното поведение.
За да се върнете към предишните си нива на производителност, отговорът е да използвате новия API за неподредено масово вмъкване . Ето една времева версия:
> 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
Сега това се връща към почти същата производителност за малко над 2 секунди. Разбира се, това е малко по-обемист (простете за играта на думи), но знаете точно какво получавате, което според мен е нещо добро като цяло. Тук има и плюс, когато не търсите информация за времето. Нека се отървем от това и стартираме вмъкването отново:
> 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" : [ ]
})
Сега получаваме хубав резултатен документ, когато правим масовото вмъкване, вместо проверка само на последните операции (всички останали във версия 2.4 бяха по същество изпрати и забрави). Тъй като това е неподредена групова операция, тя ще продължи, ако срещне грешка и докладва за всяка такава грешка в този документ. В примера по-горе няма такива, които да се видят, но е лесно изкуствено да се създаде сценарий за неуспех. Нека просто предварително да вмъкнем стойност, за която знаем, че ще се появи и следователно ще причини дублираща се ключова грешка в (по подразбиране) уникален индекс _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" : [ ]
})
Сега можем да видим колко са били успешни, кой се е провалил (и защо). Може да е малко по-сложно за настройка, но като цяло смятам, че е подобрение.
С всичко казано дотук и очертания нов предпочитан начин, има начин да принудите обвивката да се върне в наследен режим. Това има смисъл, тъй като 2.6 обвивка може да се наложи да се свързва и работи с по-стари сървъри. Ако се свържете към 2.4 сървър, това ще се погрижи вместо вас, но за да наложите въпроса за конкретна връзка, можете да изпълните:
db.getMongo().forceWriteMode("legacy");
След като сте готови, можете да се върнете към версия 2.6 с:
db1.getMongo().forceWriteMode("commands");
За действителна употреба вижте моя фрагмент crud.js . Това работи засега, но може да бъде премахнато без предупреждение по всяко време в бъдеще и наистина не е предназначено за широко използване, така че използвайте на свой собствен риск.