Đó là rất nhiều câu hỏi trong một bài đăng;) Hãy để tôi giải quyết chúng theo thứ tự thực tế:
- Mọi truy vấn có thể sử dụng nhiều nhất một chỉ mục (ngoại trừ $ cấp cao nhất hoặc các mệnh đề, v.v.). Điều này bao gồm bất kỳ phân loại nào.
- Vì những điều trên, bạn chắc chắn sẽ cần một chỉ mục tổng hợp cho vấn đề của mình hơn là các chỉ mục riêng biệt cho mỗi trường.
- Các trường có số lượng thấp (vì vậy, các trường có rất ít giá trị duy nhất trên tập dữ liệu của bạn) thường không được có trong chỉ mục vì tính chọn lọc của chúng rất hạn chế.
- Thứ tự của các trường trong chỉ mục ghép của bạn cũng quan trọng và hướng tương đối của từng trường trong chỉ mục ghép của bạn (ví dụ:"{name:1, age:-1}"). Có rất nhiều tài liệu về chỉ mục ghép và hướng trường chỉ mục trên mongodb.org nên tôi sẽ không nhắc lại tất cả ở đây.
- Sắp xếp sẽ chỉ sử dụng chỉ mục nếu trường sắp xếp nằm trong chỉ mục và là trường trong chỉ mục ngay sau trường cuối cùng được sử dụng để chọn tập kết quả. Trong hầu hết các trường hợp, đây sẽ là trường cuối cùng của chỉ mục.
Vì vậy, bạn hoàn toàn không nên đưa trạng thái vào chỉ mục của mình vì một khi quá trình lập chỉ mục đã loại bỏ phần lớn các tài liệu dựa trên các trường có số lượng cao hơn, nó sẽ chỉ còn lại 2-3 tài liệu trong hầu hết các trường hợp mà hầu như không được tối ưu hóa bởi chỉ mục trạng thái (đặc biệt là vì bạn đã đề cập đến 2-3 tài liệu đó dù sao thì rất có thể có cùng trạng thái).
Bây giờ, lưu ý cuối cùng có liên quan trong trường hợp của bạn là khi bạn sử dụng truy vấn phạm vi (và bạn cũng vậy), nó sẽ không sử dụng chỉ mục để sắp xếp. Bạn có thể kiểm tra điều này bằng cách xem giá trị "scanAndOrder" của giải thích () sau khi bạn kiểm tra truy vấn của mình. Nếu giá trị đó tồn tại và đúng, điều đó có nghĩa là nó sẽ sắp xếp tập kết quả trong bộ nhớ (quét và sắp xếp) thay vì sử dụng chỉ mục trực tiếp. Điều này không thể tránh được trong trường hợp cụ thể của bạn.
Vì vậy, chỉ mục của bạn nên là:
db.posts.ensureIndex({start:1, end:1})
và truy vấn của bạn (chỉ sửa đổi thứ tự để rõ ràng, trình tối ưu hóa truy vấn sẽ chạy truy vấn ban đầu của bạn thông qua cùng một đường dẫn thực thi nhưng tôi thích đặt các trường được lập chỉ mục trước và theo thứ tự):
db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1})