MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Cách sắp xếp hoạt động với các truy vấn `$ or` và` $ in` trong MongoDB?

Lưu ý: Câu trả lời này dựa trên MongoDB 3.2.4.

Thật đáng giá khi khám phá việc sử dụng explain() trong MongoDB. explain() đầu ra của một truy vấn (ví dụ:db.collection.explain().find(...) ) cho phép bạn kiểm tra chỉ mục nào được sử dụng trong một truy vấn và sử dụng db.collection.explain('executionStats') cũng sẽ cho bạn biết truy vấn thành công hay thất bại do SORT trong bộ nhớ giới hạn.

$ trong

Một $in truy vấn có thể được coi là một loạt các truy vấn bình đẳng. Ví dụ:{a: {$in: [1,3,5]}} có thể được coi là {a:1}, {a:3}, {a:5} . MongoDB sẽ sắp xếp $in mảng trước khi tiếp tục truy vấn, sao cho {$in: [3,5,1]} không khác gì {$in: [1,3,5]} .

Giả sử tập hợp có chỉ mục là

{a:1, b:1}
  • Sắp xếp theo a

      db.coll.find({a: {$in: [1,3,5]}}).sort({a:1})
    

    MongoDB sẽ có thể sử dụng {a:1,b:1} chỉ mục, vì truy vấn này có thể được coi là sự kết hợp của {a:1}, {a:3}, {a:5} truy vấn. Sắp xếp theo {a:1} cho phép sử dụng tiền tố chỉ mục , vì vậy MongoDB không cần thực hiện sắp xếp trong bộ nhớ.

    Tình huống tương tự cũng áp dụng cho truy vấn:

      db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})
    

    sort({a:1}) cũng sử dụng tiền tố chỉ mục (a trong trường hợp này), một SORT trong bộ nhớ do đó không bắt buộc phải có giai đoạn.

  • Sắp xếp theo b

    Đây là một trường hợp thú vị hơn so với việc sắp xếp theo a . Ví dụ:

      db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})
    

    explain() đầu ra của truy vấn này sẽ có một giai đoạn được gọi là SORT_MERGE . Hãy nhớ rằng find() một phần của truy vấn có thể được coi là {a:1}, {a:3}, {a:5} .

    Truy vấn db.coll.find({a:1}).sort({b:1}) không cần phải có SORT trong bộ nhớ giai đoạn do bản chất của {a:1,b:1} index:nghĩa là, MongoDB có thể đơn giản chỉ mục (đã sắp xếp) và trả về các tài liệu được sắp xếp theo b sau khi thỏa mãn tham số bình đẳng trên a . Ví dụ:cho mỗi a , có rất nhiều b đã được sắp xếp theo b do chỉ số.

    Sử dụng $in , truy vấn tổng thể có thể được coi là:

    • db.coll.find({a:1}).sort({b:1})
    • db.coll.find({a:3}).sort({b:1})
    • db.coll.find({a:5}).sort({b:1})
    • Lấy các kết quả truy vấn riêng lẻ ở trên và thực hiện hợp nhất bằng cách sử dụng giá trị của b . Truy vấn không cần giai đoạn sắp xếp trong bộ nhớ bởi vì các kết quả truy vấn riêng lẻ đã được sắp xếp theo b . MongoDB chỉ cần hợp nhất các kết quả truy vấn phụ (đã được sắp xếp) thành một kết quả duy nhất.

    Tương tự, truy vấn

      db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})
    

    cũng sử dụng SORT_MERGE và rất giống với truy vấn ở trên. Sự khác biệt là các truy vấn riêng lẻ xuất ra các tài liệu dựa trên một phạm vi b (thay vì mọi b ) cho mỗi a (sẽ được sắp xếp theo b do chỉ mục {a:1,b:1} ). Do đó, truy vấn không cần giai đoạn sắp xếp trong bộ nhớ.

$ hoặc

Đối với một $or truy vấn để sử dụng chỉ mục, mọi mệnh đề trong $or biểu thức phải có một chỉ mục được liên kết với nó . Nếu yêu cầu này được đáp ứng, truy vấn có thể sử dụng SORT_MERGE giống như một $in truy vấn. Ví dụ:

db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})

sẽ có một kế hoạch truy vấn, sử dụng chỉ mục và SORT_MERGE gần như giống hệt nhau như trong $in ví dụ trên. Về cơ bản, truy vấn có thể được coi là:

  • db.coll.find({a:1}).sort({b:1})
  • db.coll.find({a:3}).sort({b:1})
  • db.coll.find({a:5}).sort({b:1})
  • Lấy các kết quả truy vấn riêng lẻ ở trên và thực hiện hợp nhất bằng cách sử dụng giá trị của b .

giống như $in ví dụ trước đây.

Tuy nhiên, truy vấn này:

db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})

không thể sử dụng bất kỳ chỉ mục nào (vì chúng tôi không có {b:1} mục lục). Truy vấn này sẽ dẫn đến việc quét bộ sưu tập và do đó sẽ có giai đoạn sắp xếp trong bộ nhớ vì không có chỉ mục nào được sử dụng.

Tuy nhiên, nếu chúng tôi tạo chỉ mục {b:1} , truy vấn sẽ tiến hành như sau:

  • db.coll.find({a:1}).sort({b:1})
  • db.coll.find({b:1}).sort({b:1})
  • Lấy các kết quả truy vấn riêng lẻ ở trên và thực hiện hợp nhất bằng cách sử dụng giá trị của b (đã được sắp xếp ở cả hai truy vấn phụ, do các chỉ mục {a:1,b:1}{b:1} ).

và MongoDB sẽ kết hợp các kết quả của {a:1}{b:1} truy vấn và thực hiện hợp nhất các kết quả. Quá trình hợp nhất là thời gian tuyến tính, ví dụ:O(n) .

Tóm lại, trong $or truy vấn, mọi thuật ngữ phải có chỉ mục, bao gồm sort() sân khấu. Nếu không, MongoDB sẽ phải thực hiện sắp xếp trong bộ nhớ.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB $ tan

  2. Django-nonrel sử dụng ListField chứa EmbeddedObjects trong quản trị viên

  3. Sắp xếp hiệu quả các kết quả của truy vấn không gian địa lý mongodb

  4. Làm cách nào để trả về kết quả Mongoose từ phương thức find?

  5. Có cách nào để cập nhật nguyên tử hai bộ sưu tập trong MongoDB không?