MongoDB sắp xếp các bản ghi như thế nào khi không có thứ tự sắp xếp nào được chỉ định?


103

Khi chúng tôi chạy truy vấn Mongo find () mà không có bất kỳ thứ tự sắp xếp nào được chỉ định, cơ sở dữ liệu nội bộ sử dụng gì để sắp xếp kết quả?

Theo tài liệu trên trang web mongo :

Khi thực thi một find () không có tham số, cơ sở dữ liệu trả về các đối tượng theo thứ tự tự nhiên chuyển tiếp.

Đối với các bảng tiêu chuẩn, thứ tự tự nhiên không đặc biệt hữu ích bởi vì, mặc dù thứ tự thường gần với thứ tự chèn, nhưng nó không được đảm bảo. Tuy nhiên, đối với Bộ sưu tập có giới hạn, thứ tự tự nhiên được đảm bảo là thứ tự chèn. Điều này có thể rất hữu ích.

Tuy nhiên đối với các tập hợp chuẩn (tập hợp không giới hạn), trường nào được sử dụng để sắp xếp kết quả? Nó là trường _id hay cái gì khác?

Biên tập:

Về cơ bản, tôi đoán những gì tôi đang cố gắng đạt được là nếu tôi thực hiện truy vấn tìm kiếm sau:

db.collection.find({"x":y}).skip(10000).limit(1000);

Tại hai thời điểm khác nhau: t1t2 , tôi sẽ nhận được các tập kết quả khác nhau:

  1. Khi không có ghi bổ sung nào giữa t1 & t2?
  2. Khi nào có ghi mới giữa t1 & t2?
  3. Có chỉ mục mới đã được thêm vào giữa t1 & t2?

Tôi đã chạy một số thử nghiệm trên cơ sở dữ liệu tạm thời và kết quả tôi nhận được là giống nhau ( ) cho cả 3 trường hợp - nhưng tôi muốn chắc chắn và tôi chắc chắn rằng các trường hợp thử nghiệm của tôi không được kỹ lưỡng.

Câu trả lời:


121

Thứ tự sắp xếp mặc định là gì khi không có gì được chỉ định?

Thứ tự sắp xếp nội bộ mặc định (hoặc thứ tự tự nhiên ) là một chi tiết triển khai không xác định . Duy trì thứ tự là chi phí bổ sung cho các công cụ lưu trữ và API của MongoDB không bắt buộc khả năng dự đoán bên ngoài sort()trường hợp rõ ràng hoặc đặc biệt của các bộ sưu tập có giới hạn có kích thước cố định có các hạn chế sử dụng liên quan . Đối với khối lượng công việc điển hình, công cụ lưu trữ mong muốn cố gắng sử dụng lại không gian được phân bổ trước có sẵn và đưa ra quyết định về cách lưu trữ dữ liệu trên đĩa và trong bộ nhớ một cách hiệu quả nhất.

Không có bất kỳ tiêu chí truy vấn nào, kết quả sẽ được công cụ lưu trữ trả về theo thứ tự tự nhiên (hay còn gọi là theo thứ tự chúng được tìm thấy ). Thứ tự kết quả có thể trùng với thứ tự chèn nhưng hành vi này không được đảm bảo và không thể dựa vào (ngoại trừ các tập hợp có giới hạn).

Một số ví dụ có thể ảnh hưởng đến thứ tự lưu trữ (tự nhiên):

  • WiredTiger sử dụng cách trình bày tài liệu trên đĩa khác với bộ đệm trong bộ nhớ, vì vậy thứ tự tự nhiên có thể thay đổi dựa trên cấu trúc dữ liệu bên trong.
  • Công cụ lưu trữ MMAPv1 gốc (đã bị loại bỏ trong MongoDB 4.2) phân bổ không gian bản ghi cho các tài liệu dựa trên các quy tắc đệm. Nếu một tài liệu lớn hơn không gian bản ghi hiện được cấp phát, vị trí tài liệu (và thứ tự tự nhiên) sẽ bị ảnh hưởng. Tài liệu mới cũng có thể được đưa vào bộ nhớ được đánh dấu sẵn sàng để sử dụng lại do tài liệu bị xóa hoặc di chuyển.
  • Bản sao sử dụng một định dạng oplog không cần thiết để áp dụng các thao tác ghi một cách nhất quán trên các thành viên tập hợp bản sao. Mỗi thành viên tập hợp bản sao duy trì các tệp dữ liệu cục bộ có thể thay đổi theo thứ tự tự nhiên, nhưng sẽ có cùng kết quả dữ liệu khi áp dụng cập nhật nhật ký.

Điều gì sẽ xảy ra nếu một chỉ mục được sử dụng?

Nếu một chỉ mục được sử dụng, các tài liệu sẽ được trả về theo thứ tự chúng được tìm thấy (nhất thiết phải khớp với thứ tự chèn hoặc thứ tự I / O). Nếu nhiều hơn một chỉ mục được sử dụng thì thứ tự phụ thuộc nội bộ vào chỉ mục nào xác định tài liệu đầu tiên trong quá trình khử trùng lặp.

Nếu bạn muốn một thứ tự sắp xếp có thể dự đoán, bạn phải bao gồm một sort()truy vấn rõ ràng và có các giá trị duy nhất cho khóa sắp xếp của bạn.

Làm cách nào để các bộ sưu tập có giới hạn duy trì thứ tự chèn?

Ngoại lệ triển khai được lưu ý đối với trật tự tự nhiên trong bộ sưu tập có giới hạn được thực thi bởi các hạn chế sử dụng đặc biệt của chúng: tài liệu được lưu trữ theo thứ tự chèn nhưng không thể tăng kích thước tài liệu hiện có và không thể xóa tài liệu một cách rõ ràng. Đặt hàng là một phần của thiết kế bộ sưu tập có giới hạn để đảm bảo các tài liệu cũ nhất "hết tuổi" trước.


4
Điều này có nghĩa là nếu tôi chạy cùng một lệnh tìm: db.collection.find ({"x": y}). Bỏ qua (20000) .limit (1000) tại hai thời điểm khác nhau, tôi sẽ nhận được kết quả khác nhau bộ? Điều gì xảy ra nếu không có ghi nào giữa hai lệnh?
saurabhj

6
@saurabhj: Đã thêm một số ví dụ sẽ ảnh hưởng đến trật tự tự nhiên. Nếu tài liệu đã được di chuyển / xóa, bạn có thể nhận được các bộ kết quả khác nhau. Nếu không có tài liệu chèn / cập nhật / xóa, bạn sẽ nhận được kết quả tương tự. Việc thêm chỉ mục không ảnh hưởng đến vị trí của tài liệu trên đĩa.
Stennie

7
Cũng nên thêm cảnh báo rằng nếu bạn đang sử dụng bản sao , thứ tự tự nhiên có thể khác nhau giữa các thành viên nhóm bản sao.
Stennie

Có ai biết làm thế nào để buộc bất kỳ trong 2 điểm đã nhận xét ở đây? Chúng tôi đã thử sửa đổi tài liệu nhưng chúng vẫn được trả về theo thứ tự chèn ... Tôi tò mò về việc liệu thứ tự tự nhiên có thể khác với thứ tự chèn hay không.
Ferran Maylinch

Thực thi một thứ tự mặc định (ví dụ {createdAt: -1}) là cần thiết để triển khai các mẫu Giao diện người dùng Lạc quan (cập nhật danh sách dữ liệu trong bộ nhớ cache mà không cần đợi phản hồi của máy chủ sau khi tạo / cập nhật / xóa). Nếu không, bạn không thể khớp thứ tự lạc quan phía máy khách và thứ tự phản hồi của máy chủ.
Eric Burel

8

Nó được trả lại theo thứ tự đã lưu trữ (thứ tự trong tệp), nhưng nó không được đảm bảo rằng chúng theo thứ tự đã chèn. Chúng không được sắp xếp theo trường _id. Đôi khi nó có thể trông giống như nó được sắp xếp theo thứ tự chèn nhưng nó có thể thay đổi trong một yêu cầu khác. Nó không đáng tin cậy.

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.