Trong MongoDB, bạn có thể sử dụng cursor.explain()
hoặc db.collection.explain()
để xác định xem một truy vấn có sử dụng chỉ mục hay không.
Các phương pháp này cho phép bạn xem kế hoạch truy vấn cho truy vấn, bao gồm việc nó có sử dụng chỉ mục hay không.
Ví dụ
Giả sử chúng ta có một bộ sưu tập có tên là pets
và nó chứa các tài liệu sau:
{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 } { "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 } { "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 } { "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 } { "_id" : 5, "name" : "Bruce", "type" : "Bat", "weight" : 3 } { "_id" : 6, "name" : "Fetch", "type" : "Dog", "weight" : 17 } { "_id" : 7, "name" : "Jake", "type" : "Dog", "weight" : 30 }
Và giả sử chúng ta tạo chỉ mục sau trên name
của nó lĩnh vực:
db.pets.createIndex( { "name" : 1 } )
Bây giờ khi chúng ta chạy truy vấn sau, nó sẽ sử dụng chỉ mục đó:
db.pets.find( { "name" : "Scratch" } )
Kết quả:
{ "_id" : 4, "name" : "Scratch", "type" : "Cat", "weight" : 8 }
Nhưng chúng tôi không thể biết chỉ bằng cách nhìn vào kết quả liệu nó có sử dụng chỉ mục hay không.
Đây là nơi explain()
có phương thức. Chúng ta có thể thêm explain()
vào cuối truy vấn của chúng tôi để có được kế hoạch truy vấn. Điều đó sẽ cho chúng tôi biết liệu nó có sử dụng một chỉ mục hay không.
db.pets.find( { "name" : "Scratch" } ).explain()
Kết quả:
{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "PetHouse.pets", "indexFilterSet" : false, "parsedQuery" : { "name" : { "$eq" : "Scratch" } }, "queryHash" : "01AEE5EC", "planCacheKey" : "4C5AEA2C", "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "name" : 1 }, "indexName" : "name_1", "isMultiKey" : false, "multiKeyPaths" : { "name" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "name" : [ "[\"Scratch\", \"Scratch\"]" ] } } }, "rejectedPlans" : [ ] }, "ok" : 1 }
Chúng ta có thể thấy phần có nội dung IXSCAN
rằng truy vấn sử dụng quét chỉ mục để tạo ra kết quả.
Ngược lại, nếu chúng tôi làm tương tự đối với một truy vấn không có trong chỉ mục của chúng tôi, chúng tôi sẽ thấy rằng truy vấn đó sử dụng quét bộ sưu tập (COLLSCAN
):
db.pets.find( { "type" : "Dog" } ).explain()
Kết quả:
{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "PetHouse.pets", "indexFilterSet" : false, "parsedQuery" : { "type" : { "$eq" : "Dog" } }, "queryHash" : "2A1623C7", "planCacheKey" : "2A1623C7", "winningPlan" : { "stage" : "COLLSCAN", "filter" : { "type" : { "$eq" : "Dog" } }, "direction" : "forward" }, "rejectedPlans" : [ ] }, "ok" : 1 }
db.collection.explain()
Phương pháp
db.collection.explain()
phương thức tương tự như cursor.explain()
, ngoại trừ điều đó với db.collection.explain()
, bạn có thể xâu chuỗi các công cụ sửa đổi truy vấn bổ sung vào truy vấn (sau find()
phương pháp).
Vì mục đích của chúng tôi, chúng tôi có thể thực hiện những việc sau:
db.pets.explain().find( { "name": "Scratch" } )
Kết quả:
{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "PetHouse.pets", "indexFilterSet" : false, "parsedQuery" : { "name" : { "$eq" : "Scratch" } }, "queryHash" : "01AEE5EC", "planCacheKey" : "4C5AEA2C", "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "name" : 1 }, "indexName" : "name_1", "isMultiKey" : false, "multiKeyPaths" : { "name" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "name" : [ "[\"Scratch\", \"Scratch\"]" ] } } }, "rejectedPlans" : [ ] }, "ok" : 1 }
Bạn có thể chạy lệnh sau để truy xuất danh sách các công cụ sửa đổi truy vấn có sẵn cho phương pháp này:
db.collection.explain().find().help()