Trước 2.6, trình bao tương tác sẽ chạy qua vòng lặp và chỉ kiểm tra sự thành công (sử dụng getLastError) của thao tác cuối cùng trong vòng lặp (cụ thể hơn, nó được gọi là getLastError sau mỗi ký tự xuống dòng, với thao tác cuối cùng là lần chèn cuối cùng trong vòng lặp). Với 2.6, shell bây giờ sẽ kiểm tra trạng thái của từng hoạt động riêng lẻ trong vòng lặp. Về cơ bản, điều đó có nghĩa là "sự chậm chạp" với 2,6 có thể được quy cho hiệu suất ghi được thừa nhận so với không được công nhận chứ không phải là vấn đề hiệu suất thực tế.
Các bài viết được công nhận là mặc định trong một thời gian bây giờ và vì vậy tôi nghĩ hành vi trong 2.6 là đúng hơn, mặc dù hơi bất tiện đối với những người trong chúng ta đã từng sử dụng hành vi ban đầu.
Để quay lại mức hiệu suất trước đây của bạn, câu trả lời là sử dụng API chèn hàng loạt không có thứ tự . Đây là phiên bản hẹn giờ:
> 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
Nó bây giờ trở lại về cơ bản cùng hiệu suất chỉ hơn 2 giây. Chắc chắn, nó cồng kềnh hơn một chút (tha thứ cho cách chơi chữ), nhưng bạn biết chính xác những gì bạn đang nhận được, mà tôi nghĩ nói chung là một điều tốt. Ngoài ra còn có một điểm thuận lợi ở đây, khi bạn không tìm kiếm thông tin về thời gian. Hãy loại bỏ điều đó và chạy lại chèn:
> 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" : [ ]
})
Bây giờ chúng ta nhận được một tài liệu kết quả đẹp khi chúng ta thực hiện chèn hàng loạt, thay vì chỉ kiểm tra các thao tác cuối cùng (tất cả phần còn lại trong phiên bản 2.4 về cơ bản là gửi và quên). Bởi vì nó là một hoạt động hàng loạt không có thứ tự, nó sẽ tiếp tục nếu nó gặp lỗi và báo cáo về từng lỗi như vậy trong tài liệu này. Không có gì được nhìn thấy trong ví dụ trên, nhưng rất dễ tạo ra một kịch bản thất bại một cách giả tạo. Hãy chỉ chèn trước một giá trị mà chúng ta biết sẽ xuất hiện và do đó gây ra lỗi khóa trùng lặp trên chỉ mục _id duy nhất (mặc định):
> 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" : [ ]
})
Bây giờ chúng ta có thể xem có bao nhiêu thành công, cái nào thất bại (và tại sao). Nó có thể phức tạp hơn một chút để thiết lập, nhưng về tổng thể, tôi nghĩ đó là một cải tiến.
Với tất cả những điều đó đã nói và cách ưu tiên mới được nêu ra, có một cách để buộc trình bao quay trở lại chế độ kế thừa. Điều này có ý nghĩa, vì trình bao 2.6 có thể phải kết nối và làm việc với các máy chủ cũ hơn. Nếu bạn kết nối với máy chủ 2.4, điều này sẽ được giải quyết cho bạn, nhưng để bắt buộc vấn đề đối với một kết nối cụ thể, bạn có thể chạy:
db.getMongo().forceWriteMode("legacy");
Sau khi hoàn tất, bạn có thể hoàn nguyên về phiên bản 2.6 với:
db1.getMongo().forceWriteMode("commands");
Để biết cách sử dụng thực tế, hãy xem đoạn mã crud.js . Tính năng này hoạt động ngay bây giờ, nhưng có thể bị xóa mà không cần thông báo vào bất kỳ thời điểm nào trong tương lai và thực sự không nhằm mục đích sử dụng rộng rãi, vì vậy bạn tự chịu rủi ro khi sử dụng.