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})
vì
sort({a:1})
cũng sử dụng tiền tố chỉ mục (a
trong trường hợp này), mộtSORT
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ằngfind()
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 theob
sau khi thỏa mãn tham số bình đẳng trêna
. Ví dụ:cho mỗia
, có rất nhiềub
đã được sắp xếp theob
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 theob
. 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 vib
(thay vì mọib
) cho mỗia
(sẽ được sắp xếp theob
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}
và{b:1}
).
và MongoDB sẽ kết hợp các kết quả của {a:1}
và {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ớ.