Przed wersją 2.6 interaktywna powłoka działała przez pętlę i sprawdzała tylko powodzenie (przy użyciu getLastError) ostatniej operacji w pętli (dokładniej nazywała się getLastError po każdym powrocie karetki, przy czym ostatnią operacją jest ostatnia operacja wstawienia w pętli). W wersji 2.6 powłoka będzie teraz sprawdzać stan każdej pojedynczej operacji w pętli. Zasadniczo oznacza to, że „powolność” w wersji 2.6 można przypisać potwierdzonej lub niepotwierdzonej wydajności zapisu, a nie samemu problemowi z wydajnością.
Uznane zapisy były domyślnym od jakiegoś czasu , więc myślę, że zachowanie w wersji 2.6 jest bardziej poprawne, choć trochę niewygodne dla tych z nas, którzy są przyzwyczajeni do oryginalnego zachowania.
Aby wrócić do poprzednich poziomów wydajności, odpowiedzią jest użycie nowego interfejs API nieuporządkowanego zbiorczego wstawiania . Oto wersja czasowa:
> 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
Teraz wróciłem do zasadniczo tej samej wydajności w nieco ponad 2 sekundy. Jasne, jest trochę bardziej obszerny (przepraszam za kalambur), ale wiesz dokładnie, co dostajesz, co ogólnie uważam za dobrą rzecz. Istnieje również zaleta, gdy nie szukasz informacji o czasie. Pozbądźmy się tego i uruchom wstawkę ponownie:
> 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" : [ ]
})
Teraz otrzymujemy ładny dokument wynikowy, gdy wykonujemy zbiorcze wstawianie, zamiast sprawdzania tylko ostatnich operacji (cała reszta w wersji 2.4 była zasadniczo wysyłana i zapominana). Ponieważ jest to nieuporządkowana operacja zbiorcza, będzie kontynuowana w przypadku napotkania błędu i zgłoszenia każdego takiego błędu w tym dokumencie. W powyższym przykładzie nie widać żadnego, ale łatwo jest sztucznie stworzyć scenariusz niepowodzenia. Po prostu wstawmy wstępnie wartość, o której wiemy, że pojawi się i spowoduje błąd zduplikowanego klucza w (domyślnym) unikalnym indeksie _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" : [ ]
})
Teraz możemy zobaczyć, ile się udało, a które zawiodły (i dlaczego). Konfiguracja może być nieco bardziej skomplikowana, ale ogólnie uważam, że jest to poprawa.
Biorąc to wszystko pod uwagę i nakreślono nowy preferowany sposób, istnieje sposób na zmuszenie powłoki do powrotu do trybu starszego. Ma to sens, ponieważ powłoka 2.6 może łączyć się ze starszymi serwerami i pracować ze starszymi serwerami. Jeśli połączysz się z serwerem 2.4, zajmiemy się tym za Ciebie, ale aby wymusić sprawę dla konkretnego połączenia, możesz uruchomić:
db.getMongo().forceWriteMode("legacy");
Gdy skończysz, możesz wrócić do wersji 2.6 za pomocą:
db1.getMongo().forceWriteMode("commands");
Aby zapoznać się z rzeczywistym użyciem, zobacz mój fragment crud.js . To działa na razie, ale może zostać usunięte bez powiadomienia w dowolnym momencie w przyszłości i tak naprawdę nie jest przeznaczone do intensywnego użytkowania, więc używaj go na własne ryzyko.