Mức sử dụng dữ liệu trong bộ đệm của giai đoạn sắp xếp tràn vượt quá giới hạn nội bộ


85

Sử dụng mã:

all_reviews = db_handle.find().sort('reviewDate', pymongo.ASCENDING)
print all_reviews.count()

print all_reviews[0]
print all_reviews[2000000]

Số đếm sẽ in 2043484, và nó sẽ in all_reviews[0].

Tuy nhiên, khi in all_reviews[2000000], tôi gặp lỗi:

pymongo.errors.OperationFailure: lỗi cơ sở dữ liệu: Lỗi trình chạy: Mức sử dụng dữ liệu đệm trong giai đoạn sắp xếp tràn là 33554495 byte vượt quá giới hạn nội bộ là 33554432 byte

Làm thế nào để tôi xử lý điều này?

Câu trả lời:


118

Bạn sắp đạt đến giới hạn 32MB theo cách sắp xếp trong bộ nhớ:

https://docs.mongodb.com/manual/reference/limits/#Sort-Operations

Thêm chỉ mục vào trường sắp xếp. Điều đó cho phép MongoDB truyền tải tài liệu cho bạn theo thứ tự được sắp xếp, thay vì cố gắng tải tất cả chúng vào bộ nhớ trên máy chủ và sắp xếp chúng trong bộ nhớ trước khi gửi đến máy khách.


7
Tốt hơn nên khai báo một chỉ mục để bạn không cần phải sắp xếp trong RAM: nhanh hơn và đáng tin cậy hơn, sử dụng RAM hạn chế hơn là có khả năng không giới hạn. Nếu bạn khăng khăng, hãy biến "tìm thấy" của bạn thành một tập hợp (có thể sử dụng 100MB RAM để sắp xếp) và đặt allowDiskUse: true để thông báo cho khung tổng hợp tràn vào đĩa nếu nó vượt quá 100MB RAM. Mong đợi một hình phạt hiệu suất nghiêm trọng so với việc chỉ tuyên bố một chỉ số thích hợp. docs.mongodb.org/manual/reference/operator/aggregation/sort/…
A. Jesse Jiryu Davis

31
Trên thực tế, nó có thể được thay đổi. Bạn cần phải chạy lệnh này: db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: <limit in bytes>}). Nguồn: askubuntu.com/questions/501937/…
kumarharsh

6
Điều cần lưu ý đối với người dùng mongoose rằng việc đặt chỉ mục: true trên prop trong giản đồ của bạn sẽ khắc phục sự cố này ... mongoose sẽ đi qua tất cả các lược đồ của bạn và đảm bảo rằng các trường trên thực tế là chỉ mục trước khi khởi động ứng dụng ... đó là trừ khi bạn tắt hành vi này với mySchema.set ('autoIndex', false);
Benjamin Conant,

2
Tôi đã tạo chỉ mục trên trường sắp xếp nhưng nó vẫn cho tôi lỗi "Thao tác sắp xếp được sử dụng nhiều hơn 33554432 byte RAM tối đa" có thể là do tôi đang áp dụng thao tác khớp trước khi sắp xếp và theo mongo doc nếu bạn sử dụng khớp trước khi sắp xếp hoạt động nó sẽ bỏ qua chỉ mục và thực hiện sắp xếp bộ nhớ trên tất cả các bản ghi phù hợp.
Amol Suryawanshi 19/02/18

11
Nếu đây là câu trả lời được chấp nhận, thì nó phải bao gồm thông tin về cách thêm chỉ mục.
Philipp Ludwig

45

Như đã nói kumar_harshtrong phần nhận xét, tôi muốn thêm một điểm khác.

Bạn có thể xem việc sử dụng bộ đệm hiện tại bằng lệnh dưới đây trên admincơ sở dữ liệu:

> use admin
switched to db admin
> db.runCommand( { getParameter : 1, "internalQueryExecMaxBlockingSortBytes" : 1 } )
{ "internalQueryExecMaxBlockingSortBytes" : 33554432, "ok" : 1 }

Nó có giá trị mặc định là 32 MB (33554432 byte) . Trong trường hợp này, bạn đang thiếu dữ liệu bộ đệm, vì vậy bạn có thể tăng giới hạn bộ đệm với giá trị tối ưu được xác định của riêng bạn, ví dụ 50 MB như sau:

>  db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes:50151432})
{ "was" : 33554432, "ok" : 1 }

Chúng tôi cũng có thể đặt giới hạn này vĩnh viễn bằng tham số dưới đây trong tệp cấu hình mongodb:

setParameter=internalQueryExecMaxBlockingSortBytes=309715200

Hi vọng điêu nay co ich !!!

Note: Lệnh này chỉ hỗ trợ sau phiên bản 3.0 +


Cách đặt giới hạn này vĩnh viễn trong tệp cấu hình là gì? Tôi có một máy bộ nhớ 1 TB dành riêng cho mongo và tôi muốn đóng nó vĩnh viễn.
Samantha Atkins,

@SamanthaAtkins Tôi đã cập nhật câu trả lời để đặt điều này vĩnh viễn trong tệp cấu hình.
JERRY,

@JERRY nơi đặt vĩnh viễn trong đường ray. Rails 5 / mongoid.yml?
Prateep Kul

Tôi đã tìm thấy nó. chạy ở thiết bị đầu cuối của tôi với: mongod và làm theo thủ công zocada.com/setting-mongodb-users-beginners-guide
Prateep Kul

24

giải quyết bằng lập chỉ mục

db_handle.ensure_index([("reviewDate", pymongo.ASCENDING)])

được chắc chắn không sử dụng một chỉ số thưa thớt, họ đang bỏ qua nếu bạn sắp xếp trên tất cả các tài liệu
Charly Koza

15

Nếu bạn muốn tránh tạo chỉ mục (ví dụ bạn chỉ muốn kiểm tra nhanh và nhanh để khám phá dữ liệu), bạn có thể sử dụng tính năng tổng hợp với việc sử dụng đĩa:

all_reviews = db_handle.aggregate([{$sort: {'reviewDate': 1}}], {allowDiskUse: true})

(Tuy nhiên, không chắc chắn cách thực hiện điều này trong pymongo).


Trong pymongo sẽ là db_handle.aggregate(pipe, allowDiskUse=True). Xem câu hỏi này để biết thêm thông tin!
Genarito

3

Cú pháp API JavaScript cho chỉ mục:

db_handle.ensureIndex({executedDate: 1})

2

Trong trường hợp của tôi, cần phải sửa các chỉ mục nessary trong mã và tạo lại chúng:

rake db:mongoid:create_indexes RAILS_ENV=production

Vì tràn bộ nhớ không xảy ra khi có chỉ mục cần thiết của trường.

PS Trước đây, tôi phải vô hiệu hóa các lỗi khi tạo các chỉ mục dài:

# mongo
MongoDB shell version: 2.6.12
connecting to: test
> db.getSiblingDB('admin').runCommand( { setParameter: 1, failIndexKeyTooLong: false } )

Cũng có thể cần reIndex:

# mongo
MongoDB shell version: 2.6.12
connecting to: test
> use your_db
switched to db your_db
> db.getCollectionNames().forEach( function(collection){ db[collection].reIndex() } )
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.